java学习-三个修饰符

三个修饰符

abstract

  • 抽象的类:

    public class TestAbstract {
    public static void main(String[] args) {
    Animal aNimal = new Dog();
    aNimal.eat();
    }
    }

    abstract class Animal {
     public Animal() {}
     
     public void eat() {
     System.out.println("动物在吃东西...");
    }
     public abstract void sleep() {}
    }

    class Dog extends Animal {
     public void eat() {
     System.out.println("狗吃骨头...");
    }
     
     public void sleep() {
     System.out.println("狗在趴着睡觉...");
    }
    }
    1. 抽象的类不能通过 new的形式创建对象;

    2. 可被子类继承,继承方式和普通类的继承一样

    3. 抽象类可以声明为引用,如上面的Animal

    4. 抽象类中不一定有抽象方法

  • 抽象方法

    public abstract void eat() {}
    1. 抽象方法只声明不实现,所有的实现都放在继承的子类中--比如所有动物都有吃的方法,但每种动物吃的东西不一样,所以Animal只是说明但凡继承这个类的动物都要有吃的方法;

    2. 抽象方法必须放在抽象类中;

    3. 子类在继承抽象类后,必须实现其所有的抽象方法,否则子类还是抽象类;如上面的eat方法在子类中的实现:public void eat() { System.out.println("狗吃骨头..."); }

static

  1. 静态可以修饰属性和方法

  2. 静态成员是全类所有对象共享的成员

  3. 不必创建对象,静态成员可以直接通过类名访问的,如下面的count可以直接通过Dog.count访问。类似还有Arrays.copyOf()等。

  • 类的实例属性和静态属性

    • 实例属性:通过类new出来的每一个对象各自持有独立的空间,互补影响。

    • 静态属性:整个类持有一个共享空间,任何一个对象修改都会影响其他对象。

      public class TestStatic {
      public static void main(String[] args) {
      Dog dog1 = new Dog();
      Dog dog2 = new Dog();
      dog1.name = "nana";
      dog2.name = "nini";
      dog1.type = "walking";
      dog2.type = "dating";
      System.out.println("dog1-name:"+dog1.name);  // nana
      System.out.println("dog1-type:"+dog1.type);  // dating
      System.out.println("dog2-name:"+dog2.name);  // nini
      System.out.println("dog2-type:"+dog2.type);  // dating
      }
      }

      class Dog {
      String name;
      static String type;
      }

       

       

    • 静态属性的应用-计算一个类被创建了对象多少次

      class Dog {
      String name;
      static String type;
      static int count;

      public Dog() {
      this.count ++;
      }
      }

       

  • 局部方法、实例方法和静态方法

    class Dog {
       public static void eat() {...}  // 静态方法
       public void sleep() {...} // 实例方法
    }
    • 静态方法允许直接访问静态成员,但不能直接访问非静态成员

    • 静态方法内不允许使用this或super关键字(那怎么访问静态属性

    • 静态方法可以被继承,但是不能被重写、没有多态

  • 静态代码块和动态代码块

    class MyClass {
    String field = "实例属性1";
    static String staticField = "静态属性1";

    public MyClass() {
    System.out.println("构造方法");
    }

    { // 动态代码块
           // 给实例属性赋值或者进行一些初始化操作
    System.out.println("field: "+ field);
    System.out.println("staticField: "+ staticField);
    System.out.println("动态代码块");
    }

    static {  // 静态代码块
           // 给静态属性赋值或者进行一些初始化操作
    System.out.println("staticField: "+ staticField);
    System.out.println("静态代码块");
    }
    }
    new MyClass();
    new MyClass();
    // 执行结果如下

     

    1. 执行时间:静态属性的初始化和静态代码块只在类被加载时执行一次,此后再也不会执行(且静态代码中不能有非静态属性);动态代码块在每次实例化对象的时候都会执行一次。

    2. 执行顺序:静态属性>静态代码块>实例属性>动态代码块>构造方法

  • 带有继承的对象创建过程

    class Super {
    String field = "父类实例属性";
    static String staticField = "父类静态属性";

    public Super() {
    System.out.println("父类构造方法");
    }

    {
    System.out.println("field: "+ field);
    System.out.println("staticField: "+ staticField);
    System.out.println("父类动态代码块");
    }

    static {
    System.out.println("staticField: "+ staticField);
    System.out.println("父类静态代码块");
    }
    }

    class Sub extends Super {
    String field = "子类实例属性";
    static String staticField = "子类静态属性";

    public Sub() {
    System.out.println("子类构造方法");
    }

    {
    System.out.println("field: "+ field);
    System.out.println("staticField: "+ staticField);
    System.out.println("子类动态代码块");
    }

    static {
    System.out.println("staticField: "+ staticField);
    System.out.println("子类静态代码块");
    }
    }
    new Sub();
    System.out.println("-----------------------");
    new Sub();
    // 执行结果如下:

     

 

  • 类加载顺序

     

final

  • final修饰类,此类不能被继承。比如:String、Math、System等

  • final修饰方法:此方法不能被修改,既子类不能以覆盖的形式修改

  • final修饰变量:既我们通常意义上的常量。此类常量不再提供默认值,且不能没有值,必须手动赋予初始值。只能被赋值一次。

    • 基本类型常量(num):赋值时机:声明变量时/ 声明过后(如下面的:num = 1

    • 引用类型常量(nums): 赋值时机与上相同。不同的是,只要保证引用类型常量指向的堆地址不变即可

    • 实例常量(field): 赋值时机: 声明时、动态代码块、构造方法(如果在构造方法内赋值,就必须保证每个构造方法都能被正确赋值)

    • 静态常量(staticField):赋值时机:声明时、静态代码块

    class TestFinal {
       final String field;
       
    public void aVar() {
    final int num; // 普通变量
           final int[] nums = new int[]{1,2,3};
           nums[1] = 4; // 最终指向的地址堆不变,正常运行
           nums = new int[]{1}; // 报错,改变了地址
    num = 1;
    System.out.println(num);
    }
    }

 

posted on 2022-05-18 14:40  妖娆的油条2号  阅读(43)  评论(0)    收藏  举报

导航