[Java]public、protected、private、default以及static、final

一、访问控制修饰符-public、protected、private、default

1、类访问权限

类的访问有public、default两种访问控制修饰符,其中public指可以被任何包的类访问,定义为default(即类前没有定义修饰符)指只能当前包的类访问。

2、类成员访问权限

类成员的访问有public、private、protected、default四种访问控制修饰符,其中public可以被任何包的类访问,default指可以被当前包的类访问,protected指能被相同包内的类以及其他包内的子类访问,private只能被当前类访问。

 

二、非访问控制修饰符-static、final

1、static

static可以修饰属性、方法、内部类和代码块。

(1)静态属性

用static修饰类中的成员和方法后即成为类的属性和方法,使用方法为类名.属性或方法。静态属性由整个类共享,不需要依赖于具体的对象而存在,实际上就是一个共享的变量。

代码示范:

public class TestStatic {
    private static int i = 0;
    public TestStatic(){
        i++;
    }

    public static void main(String[] args){
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
    }
}

输出:

1
2
3
4
5

无static修饰属性的代码:

public class TestStatic {
    private int i = 0;
    public TestStatic(){
        i++;
    }

    public static void main(String[] args){
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
    }
}

输出:

1
1
1
1
1

由此可见,用static修饰的属性是共享的,而不会随每次实例化而出来一个新的i。

(2)静态方法

在开发的过程中我们会经常需要写一些工具类来减少我们的代码量,这个时候它们可以直接通过类来调用,而不用实例化对象,这就是静态方法。静态方法只能访问静态变量和局部变量,不能访问类的属性。静态方法是不能被覆盖的(但可以重载),虽然子类中可以有同名的静态方法。

(3)静态代码块

在定义类时使用静态代码块对静态属性进行初始化,当Java运行时装载类时,尽在第一次装载才会执行这段代码。

代码示范:

public class TestStatic {
    private static int i = 0;
    static {
        i++;
    }

    public static void main(String[] args){
        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
    }
}

输出:

1
1

而用非静态代码块时:

public class TestStatic {
    private static int i = 0;
    {
        i++;
    }
    
    public static void main(String[] args){

        System.out.println(new TestStatic().i);
        System.out.println(new TestStatic().i);
    }
}

输出:

1
2

由上面代码可以看出静态代码块和非静态代码块的区别了。

 

面试提问点:初始化顺序

类属性的初始化可以通过静态代码块和构造方法来实现。

Parent:

public class Parent {
    public static int total;
    public static final int base;
    static {
        System.out.println("ParentStatic执行");
        total = 0;
        base = 100;
    }
    public Parent(){
        System.out.println("Parent执行");
        total++;
    }
}

Child:

public class Child extends Parent {
    private int sid;
    public Child(){
        sid = Parent.base+Parent.total;
        System.out.println("子类编号:"+sid);
    }
}

Test:

public class Test {
    public static void main(String[] args){
        System.out.println("Parent对象:"+Parent.total);
        System.out.println("Parent初始编号:"+Parent.base);
        new Child();
        new Child();
        new Child();
    }
}

输出结果为:

ParentStatic执行
Parent对象:0
Parent初始编号:100
Parent执行
子类编号:101
Parent执行
子类编号:102
Parent执行
子类编号:103

由输出结果可知:首先会执行静态代码块,然后再执行实例化,执行实例化时限制性父类的构造方法,再执行子类的构造方法。

2、final

(1)final修饰的类不能被继承,使得其中的方法也不能被继承覆盖

(2)final修饰的方法不能被子类覆盖

(3)final修饰的变量使其成为常量,只能赋值一次,只能直接赋值或者在构造方法内赋值

(4)final不允许修饰构造方法、抽象类、抽象方法

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注