Linxu磁盘 方法 dedecms jsp magento types matlab向上取整 arduino request Draggabilly vue双向绑定 bootstrap后台管理系统模板 后台页面模板 jquery选择器找子元素 jq延时 nodejs后端开发 python编程 mysql连接 python最大值 python3教程 python使用教程 python中的zip python文件写入 python中for循环的用法 配置python环境 python中set的用法 java在线学习 stringjava java的数据结构 java的环境配置 java时间戳转时间 java判断文件是否存在 狮子狗出装 在线pr序列设置 微信超级好友 java疯狂讲义 labview宝典 dnf男柔道加点 php四舍五入 疯狂java讲义
当前位置: 首页 > 学习教程  > 编程语言

Java之三个修饰符

2021/1/13 20:44:14 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

三个修饰符 文章目录三个修饰符一、abstract1.1 在class前面使用1.2 在方法前面使用二、static2.1 在属性前面使用2.2 在方法前面使用2.3 代码块2.4 加载类2.5 静态代码块2.6有继承的情况下代码执行顺序三、final关键字一、abstract 1.1 在class前面使用 大多数情况下&#xf…

三个修饰符

文章目录

      • 三个修饰符
        • 一、abstract
          • 1.1 在class前面使用
          • 1.2 在方法前面使用
        • 二、static
          • 2.1 在属性前面使用
          • 2.2 在方法前面使用
          • 2.3 代码块
          • 2.4 加载类
          • 2.5 静态代码块
          • 2.6有继承的情况下代码执行顺序
        • 三、final关键字

一、abstract

1.1 在class前面使用

大多数情况下,父类是相对比较抽象的概念,无法直接具体化成一个对象,只能够找到其子类的对象。

此时,在程序中,直接创建父类的对象是没有被限制的,可以通过在class关键字前面加上abstract关键字,让该父类只能够被继承,不能直接创建对象使用。

这种情况下,该父类的作用仅仅是为了代码在子类中复用。

public abstract class Animal {
	private String breed; // 品种
	private int age;
	private String sex;
	
	public void eat() {
		System.out.println("动物在吃");
	}
    // 省略geter和setter
}
public class Dog extends Animal{
	private String furColor;
	
	@Override
	public void eat() {
		System.out.println("狗在吃骨头");
	}
	
	public void playBall() {
		System.out.println("狗开心的在接球。。。");
	}
}

public class Cat extends Animal{
	@Override
	public void eat() {
		System.out.println("猫在吃。。。");
	}
	
	public void giao() {
		System.out.println("猫开心的叫giao...");
	}
}
public class Test {

	public static void main(String[] args) {
		Dog dog = new Dog();
		Cat cat = new Cat();
		Animal animal = new Cat();

		// Animal animal2 = new Animal(); // 此代码会出错
	}
}
1.2 在方法前面使用

上面的示例中,由于父类不能直接创建对象,而在子类中都重写了eat方法,所以父类的eat方法其实永远都不需要调用,那么可以声明为抽象方法,即在方法前面加上abstract关键字。

当一个方法前面有abstract关键字时,此类必须要加上abstract关键字。

其子类必须要重写此方法,如果不重写,需要将子类也声明为抽象类。

注意:一个抽象类里面可以没有抽象方法。

但是一个抽象方法必然存在于一个抽象类中。

public abstract class Animal {
	private String breed; // 品种
	private int age;
	private String sex;
	
	public abstract void eat(); // 声明为抽象方法
    
    // 省略geter和setter
}
public class Dog extends Animal{
	private String furColor;
	
	@Override
	public void eat() {
		System.out.println("狗在吃骨头");
	}
	
	public void playBall() {
		System.out.println("狗开心的在接球。。。");
	}
}

public class Cat extends Animal{
	@Override
	public void eat() {
		System.out.println("猫在吃。。。");
	}
	
	public void giao() {
		System.out.println("猫开心的叫giao...");
	}
}
public class Test {

	public static void main(String[] args) {
		Dog dog = new Dog();
		Cat cat = new Cat();
		Animal animal = new Cat();

		// Animal animal2 = new Animal(); // 此代码会出错
	}
}

二、static

2.1 在属性前面使用

在类中定义的普通属性,又叫实例(对象)属性,对于每个对象都会分配独立的空间来存储,相互之间不会有任何影响。

public class Student {
	public String name;
}

public static void main(String[] args) {
    Student stu1 = new Student();
    stu1.name = "张三";

    Student stu2 = new Student();
    stu2.name = "李四";

    System.out.println(stu1.name); // 输出张三
    System.out.println(stu2.name); // 输出李四
}

在属性前面加上static关键字,表示整个类无论创建多少对象,共享同一块存储空间,相互之间操作时会有影响。

public class Student {
	public String name;
    public static String classes;
}

public static void main(String[] args) {
    Student stu1 = new Student();
    stu1.name = "张三";
    stu1.classes = "a";

    Student stu2 = new Student();
    stu2.name = "李四";
    stu2.classes = "b";

    System.out.println(stu1.name); // 输出张三
    System.out.println(stu1.classes); // 输出a
    System.out.println(stu2.name); // 输出李四
    System.out.println(stu2.classes); // 输出b
}

上面的代码,会发现每次使用classes属性时,前面都有警告,当按照警告的提示去修改后,发现这个属性不需要使用对象访问,可以直接使用类名访问。更加说明是类公有的属性,而不是对象独有的属性。

public static void main(String[] args) {
    Student stu1 = new Student();
    stu1.name = "张三";
    Student.classes = "a";

    Student stu2 = new Student();
    stu2.name = "李四";
    Student.classes = "b";

    System.out.println(stu1.name);
    System.out.println(Student.classes);
    System.out.println(stu2.name);
    System.out.println(Student.classes);
}

进一步发现,既然是类共有的,不是对象独有的,那么在没有创建对象时是否可以使用呢?修改代码后,发现不需要创建对象也可以使用,确实证明是类共有的存储空间。

public static void main(String[] args) {
    Student.classes = "a";

    Student.classes = "b";

    System.out.println(Student.classes);

    System.out.println(Student.classes);
}

案例:统计对象创建的次数:

public class Student {
	public String name;
	public static String classes;
	public static int count = 0;
	
	public Student() {
		count++;
		System.out.println("构造方法被调用");
	}
}
Random random = new Random();
int num = random.nextInt(100);
System.out.println("准备创建的次数为:" + num);
for (int i = 0; i < num; i++) {
    new Student();
}
System.out.println("创建的次数为:" + Student.count);
2.2 在方法前面使用

在方法前面加上static关键字,表示该方法为静态方法,与类有关,与对象无关,不需要创建对象即可使用,通过类名调用。

类属性、类方法、实例属性、实例方法、this、super

注意:

类方法:

  • 可以调用类属性
  • 可以调用其他类方法
  • 不能调用实例属性
  • 不能调用实例方法
  • 不能调用this、super关键字

实例方法:

  • 可以调用类属性
  • 可以调用类方法
  • 可以调用实例属性
  • 可以调用实例方法
  • 可以调用this、super关键字

static方法只能调用static相关的属性和方法。

2.3 代码块

代码块是指在类中直接使用{}中的代码。会随着对象的创建而执行。

执行次序:

分配空间

属性初始化

代码块执行

构造方法执行

public class A {
	String name = "aaa";
	
	// 代码块
	{
		System.out.println(this.name);
		System.out.println("代码块被调用");
	}
	
	public A() {
		System.out.println("A的构造方法被调用");
	}
}
2.4 加载类

加载类时,会初始化静态属性,并执行静态代码块。

创建对象时才会去执行代码块和构造方法。

简单来说,加载类的作用是将类的描述加载到内存中,以便于创建对象。

Class c = Class.forName("com.qf.day13.usestatic.A"); // 加载类
A a = (A)c.newInstance(); // 创建对象
2.5 静态代码块

使用static关键字修饰的代码块,叫静态代码块。

静态代码块在加载类时执行。创建对象时会先加载类。

执行次序:

静态属性初始化

静态代码块执行

属性初始化

代码块执行

构造方法执行

public class A {
	String name = "aaa";
	static String count = "10";
	
	// 代码块
	{
		System.out.println("代码块被调用====" + this.name);
	}
	
	// 静态代码块
	static {
		System.out.println("静态代码块被调用-----" + count);
	}
	
	public A() {
		System.out.println("A的构造方法被调用");
	}
}
2.6有继承的情况下代码执行顺序

如果类B继承A,则在创建B类对象时,需要先加载B类,然而B继承了A,所以先要加载类A,所以最终的执行次序:

A加载(静态属性的初始化,静态代码块的执行)

B加载(静态属性的初始化,静态代码块的执行)

A创建对象(属性的初始化,代码块的执行,构造方法的执行)

B创建对象(属性的初始化,代码块的执行,构造方法的执行)

public class A {
	String name = "aaa";
	static String count = "10";
	
	// 代码块
	{
		System.out.println("A类中代码块被调用====" + this.name);
	}
	
	// 静态代码块
	static {
		System.out.println("A类中静态代码块被调用-----" + count);
	}
	
	public A() {
		System.out.println("A的构造方法被调用");
	}
}
public class B extends A{
	String n = "bbb";
	static String c = "20";
	
	// 代码块
	{
		System.out.println("B类中代码块被调用====" + this.n);
	}
	
	// 静态代码块
	static {
		System.out.println("B类中静态代码块被调用-----" + c);
	}
	
	public B() {
		System.out.println("B类中的构造方法被调用");
	}
}

注意:类加载只会加载一次,加载后常驻内存。所以静态代码块只会在加载时执行一次。通常用来进行一些初始化工作。

三、final关键字

  • 当final修饰类时,表示该类不能被继承。
  • 当final修饰方法时,表示该方法不能被重写。
  • 当final修饰变量时,表示该变量不能被再次赋值(只能赋值一次),即为常量。
  • 常量一般命名规则不同于变量,需要全部大写,每个单词用下划线隔开。
// 在参数中将变量变常量
public void m(final int num) {
    // num = 5; 此行代码错误,不能再次赋值
}

public static void main(String [] args){
    final int n;
    n = 5;
    // n = 6;此行代码错误,只能够赋值一次,不能更改
}
public class A {
	final String CURRENT_CLASS_NAME = "aaa"; // 常量的命名规则是全大写,下划线隔开
}
// 如果以常量作为属性,一般会定义成public static final

应用场景:

  • 通常来说,如果一个类本来就比较复杂,不需要其他类来继承它,并复用其代码,并扩展新的功能。此时可以加上final来修饰该类,例如:String
  • 如果一个方法作用已经不需要更新新的版本,需要在所有的子类中以原来功能而存在,则可以设定final,让其不能被重写。
  • 常量用途就比较广泛了,一般是在项目中定义一些不需要改动的固定的量。例如:圆周率的值

注意:当final修饰基本数据类型时,存储的就是值,所以值不能改。

当final修饰引用数据类型时,存储的是该对象或数组的地址,所以该地址不能改,但是改地址存储的内容可以修改。

final int i = 5;
// i = 6; 代码错误,基本数据类型值不能改

final int [] n = {1,2,3};
n[0] = 5;// 引用数据类型,对应地址存储的内容值可以改
// n = new int[] {2,3,4}; // 代码错误,地址不能改

final A a = new A();
a.name = "hello"; // 引用数据类型,对应地址存储的内容值可以改
a.name = "world";
// a = new A(); // 代码错误,地址不能改

本文链接: http://www.dtmao.cc/news_show_600433.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?