• Java修饰符


    一、访问修饰符

    1.顾名思义,"访问修饰符"就是和访问权限有关得修饰符。

    JAVA 的类(外部类)有 2 种访问权限: public、default。

    而方法和变量有 4 种:public、default、protected、private。

    其中默认访问权限和 protected 很相似,有着细微的差别。

    •  public 意味着任何地方的其他类都能访问。
    •  default 则是同一个包的类可以访问。
    •  protected 表示同一个包的类可以访问,其他的包的该类的子类也可以访问。
    •  private 表示只有自己类能访问。

    2.这里重点说一下受保护的访问修饰符-protected

    protected 需要从以下两个点来分析说明:

    • 子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;

    • 子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。

    package p1;
    public class Father1 {
        protected void f() {}    // 父类Father1中的protected方法
    }
     
    package p1;
    public class Son1 extends Father1 {}
     
    package p11;
    public class Son11 extends Father1{}
     
    package p1;
    public class Test1 {
        public static void main(String[] args) {
            Son1 son1 = new Son1();
            son1.f(); // Compile OK     ----(1)
            son1.clone(); // Compile Error     ----(2)
     
            Son11 son = new Son11();    
            son11.f(); // Compile OK     ----(3)
            son11.clone(); // Compile Error     ----(4)
        }
    }

    对于上面的示例,首先看(1)(3),其中的f()方法从类Father1继承而来,其可见性是包p1及其子类Son1和Son11,而由于调用f()方法的类Test1所在的包也是p1,因此(1)(3)处编译通过。其次看(2)(4),其中的clone()方法的可见性是java.lang包及其所有子类,对于语句"son1.clone();"和"son11.clone();",二者的clone()是继承了Object类的方法,在类Son1、Son11中是可见的,但对Test1是不可见的,因此(1)(3)处编译不通过。

    package p2;
    class MyObject2 {
        protected void say() {
           System.out.println("我是父类的say方法!")
        }
    }
     
    package p22;
    public class Test2 extends MyObject2 {
        public static void main(String args[]) {
           MyObject2 obj = new MyObject2();
           obj.say(); // Compile Error         ----(1)
     
           Test2 tobj = new Test2();
           tobj.say(); // Complie OK         ----(2)
        }
    }

    对于(1)而言,say()方法来自于类MyObject2本身,因此其可见性为包p2及MyObject2的子类,虽然Test2是MyObject2的子类,但在Test2中不能访问基类MyObject2的protected方法say(),因此编译不通过;对于(2)而言,由于在Test2中访问的是其本身实例的从基类MyObject2继承来的的say(),因此编译通过。

    3.访问修饰符中一些值得注意得地方:

    Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据;

    被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问;

    protected 访问修饰符不能修饰类和接口,方法和成员变量能够声明为 protected,但是接口的成员变量和成员方法不能声明为 protected;

    二、非访问修饰符

    1.abstract

    可以修饰:方法  类   接口 

    【抽象类】
     ①.使用abstract关键字修饰类,称为抽象类
     ②.抽象类不能被实例化
     【抽象方法】
     ①.被abstract修饰的没有方法体的方法
     ②.非抽象类继承抽象类,那么子类必须重写父类所有的抽象方法
     ③.抽象方法必须在抽象类中,但抽象类中不都是抽象方法

    【接口】

    ①接口定义时使用interface关键字,默认用abstract修饰此关键字了;

    ②接口里的方法即使不写abstract依然是抽象方法,因为默认使用abstract修饰

    2.static

    可以修饰: 方法 属性  内部类(不可修饰外部类)

    ①.static修饰的属性 (静态属性)也叫类属性
    ②.static修饰的方法(静态方法)也叫类方法
    ③.推荐使用:类名.属性名 类名.方法名()来调用   (也可以使用对象调用)但不推荐
    ④.类属性和类方法是属于类的,在类加载时就加载,成员属性和成员方法在对象创建时才加载
     因此静态属性和静态方法先于非静态属性和方法, 所以静态方法中不能调用非静态属性,非静态方法可以调用静态属性
    ⑤.静态方法不能使用this,super关键字;因为他两个代指子类对象和父类对象而静态比对象加载的早

    ⑥.由于类属性和类方法是属于类的,因此只会在类装载时产生一份,因此该类的多个实例只能使用同一个静态属性和方法(下面代码辅助理解该条)

    public class Demo03_Static {
        //定义静态属性和静态方法
        public static int a = 1 ;
        public static void add() {
            a++;
        }
        //定义成员属性和方法
        public int b = 1;
        public void add1(){
            b++;
        }
    }
    public class Demo03_Static2 {
        public static void main(String[] args) {
            //调用静态方法改变静态属性
            Demo03_Static d1 = new Demo03_Static();
            d1.add();//本来应该使用Demo03_Static.add();来调用静态方法这里为了方便理解没有使用
            System.out.println(d1.a);//本来应该使用Demo03_Static.a;来调用静态属性
            Demo03_Static d2 = new Demo03_Static();
            d2.add();//同上
            System.out.println(d2.a);
            //调用成员方法改变成员属性
            System.out.println("----------------------------------");
            Demo03_Static d3 = new Demo03_Static();
            d3.add1();
            System.out.println(d3.b);
            Demo03_Static d4 = new Demo03_Static();
            d4.add1();
            System.out.println(d4.b);
            
        }
    }

    运行结果:

    ※⑦.父类中的静态方法可以被继承、但不能被子类重写。

    ※⑧.如果在子类中写一个和父类中一样的静态方法,那么该静态方法由该子类特有,两者不构成重写关系。

    public class Demo03_Static {
        //定义静态属性和方法
        public static int a = 1 ;
        public static void add() {
            a++;
            System.out.println("父类的静态方法!");
        }
    }
    public class Demo03_StaticSon extends Demo03_Static{
        
        public static void add(){//√,是子类自己的静态方法,和父类的方法不构成重写
            System.out.println("调用子类和父类同名的静态方法");
        }
        
        /*public void add(){//×,不能和父类静态方法重名
    }
    */ public static void main(String[] args) { Demo03_Static d = new Demo03_StaticSon(); d.add();//测试能否重写父类的静态方法(多态本来是调用子类重写的父类方法,但是若调用父类自己的方法,说明没有重写该方法); } }

    运行结果:

    3. final

    可以修饰:方法  属性  局部变量  类(非抽象类)

    1.final修饰的类为最终类,不能被继承

    2.final修饰的方法不能被重写,但可以被继承

    3.final修饰的变量不能被修改为常量

    4.final以及final static修饰的变量的初始化方式:

     //-----------------成员变量------------------//  
        //初始化方式一,在定义变量时直接赋值  
        private final int i = 3;  
      
        //初始化方式二,声明完变量后在构造方法中为其赋值  
        //如果采用用这种方式,那么每个构造方法中都要有j赋值的语句  
        private final int j;  
      
        public FinalTest() {  
            j = 3;  
        }  
      
        //如果取消该构造方法的注释,程序就会报错,因此它没有为j赋值  
        /*public FinalTest1(String str) { 
     
        }*/  
      
        //为了方便我们可以这样写  
        public FinalTest(String str) {  
            this();  //调用无参构造器
        }  
      
        //下面的代码同样会报错,因为对j重复赋值  
        /*public FinalTest1(String str1, String str2) { 
            this(); 
            j = 3; 
        }*/  
      
      
        //初始化方式三,声明完变量后在构造代码块中为其赋值  
        //如果采用此方式,就不能在构造方法中再次为其赋值  
        //构造代码块中的代码会在构造函数之前执行,如果在构造函数中再次赋值,  
        //就会造成final变量的重复赋值  
        private final int k;  
      
        {  
            k = 4;  
        }  
      
        //-----------------类变量(静态变量)------------------//  
        //初始化方式一,在定义类变量时直接赋值  
        public final static int p = 3;  
      
        //初始化方式二,在静态代码块中赋值  
        //成员变量可以在构造函数中赋值,但是类变量却不可以。  
        //因此成员变量属于对象独有,每个对象创建时只会调用一次构造函数,  
        //因此可以保证该成员变量只被初始化一次;  
        //而类变量是该类的所有对象共有,每个对象创建时都会对该变量赋值  
        //这样就会造成变量的重复赋值。  
        public final static int q;  
      
        static {  
            q = 3;  
        }
  • 相关阅读:
    2.2 与球体相交-几何解
    2.1 与球体的交点 -代数解
    2 必要的光线追踪算法=>光线球体的相交和映射
    3.1 Matrix Properties
    chapter 3:Matriices
    4.8 渲染方程
    webstorm 皮肤(Sublime text)设置
    数字键盘(纯js)
    ios中设置readonly还会有光标?
    JS重要的坑
  • 原文地址:https://www.cnblogs.com/ytsbk/p/8747003.html
Copyright © 2020-2023  润新知