final关键字

final关键字主要用在三个地方:变量、方法、类。

  1. 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
  2. 当用final修饰一个类时,表明这个类不能被继承。final类中的所有成员方法都会被隐式地指定为final方法。
  3. 使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的Java版本已经不需要使用final方法进行这些优化了)。类中所有的private方法都隐式地指定为final。

Static关键字

  1. 修饰成员变量和成员方法: 被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用。被static 声明的成员变量属于静态成员变量,静态变量 存放在 Java 内存区域的方法区。调用格式:类名.静态变量名 类名.静态方法名()

    静态变量存放在java内存区域的方法区,

  2. 静态代码块: 静态代码块定义在类中方法外, 静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。 该类不管创建多少对象,静态代码块只执行一次.

    静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问。

    静态代码块可能在第一次new的时候执行,但不一定只在第一次new的时候执行。比如通过 Class.forName("ClassDemo")创建 Class 对象的时候也会执行,即一个类的静态代码块只会执行一次。非静态代码块每次new都会运行。

    静态代码块是主动执行的,不需要创建对象就可以执行,如调用类的静态方法时会先执行静态代码块。

    public class Test {
        public Test() {
            System.out.print("默认构造方法!--");
        }
    
        //非静态代码块
        {
            System.out.print("非静态代码块!--");
        }
    
        //静态代码块
        static {
            System.out.print("静态代码块!--");
        }
    
        private static void test() {
            System.out.print("静态方法中的内容! --");
            {
                System.out.print("静态方法中的代码块!--");
            }
    
        }
    
        public static void main(String[] args) {
            Test test = new Test();
            Test.test();//静态代码块!--静态方法中的内容! --静态方法中的代码块!--
        }
    }
    

    上述代码输出:

    静态代码块!--非静态代码块!--默认构造方法!--静态方法中的内容! --静态方法中的代码块!--Copy to clipboardErrorCopied

    当只执行 Test.test(); 时输出:

    静态代码块!--静态方法中的内容! --静态方法中的代码块!--Copy to clipboardErrorCopied

    当只执行 Test test = new Test(); 时输出:

    静态代码块!--非静态代码块!--默认构造方法!--
  3. 静态内部类(static修饰类的话只能修饰内部类): 静态内部类与非静态内部类之间存在一个最大的区别: 非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有。没有这个引用就意味着:1. 它的创建是不需要依赖外围类的创建。2. 它不能使用任何外围类的非static成员变量和方法。

    //静态内部类实现单例模式
    public class Singleton {
    
        //声明为 private 避免调用默认构造方法创建对象
        private Singleton() {
        }
    
       // 声明为 private 表明静态内部该类只能在该 Singleton 类中被访问
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
    
        public static Singleton getUniqueInstance() {
            return SingletonHolder.INSTANCE;
        }
    }

    当 Singleton 类加载时,静态内部类 SingletonHolder 没有被加载进内存。只有当调用 getUniqueInstance()方法从而触发 SingletonHolder.INSTANCE 时 SingletonHolder 才会被加载,此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次。

    这种方式不仅具有延迟初始化的好处,而且由 JVM 提供了对线程安全的支持。

  4. 静态导包(用来导入类中的静态资源,1.5之后的新特性): 格式为:import static 这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法。

this关键字

用于引用类的当前实例。

super关键字

用于从子类访问父类的变量和方法。

public class Super {
    protected int number;

    protected showNumber() {
        System.out.println("number = " + number);
    }
}

public class Sub extends Super {
    void bar() {
        super.number = 10;
        super.showNumber();
    }
}

使用 this 和 super 要注意的问题:

  • 在构造器中使用 super() 调用父类中的其他构造方法时,该语句必须处于构造器的首行,否则编译器会报错。另外,this 调用本类中的其他构造方法时,也要放在首行。
  • this、super不能用在static方法中。

简单解释一下:

被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享。而 this 代表对本类对象的引用,指向本类对象;而 super 代表对父类对象的引用,指向父类对象;所以, this和super是属于对象范畴的东西,而静态方法是属于类范畴的东西

静态方法与非静态方法

静态方法属于类本身,非静态方法属于从该类生成的每个对象。 如果您的方法执行的操作不依赖于其类的各个变量和方法,请将其设置为静态(这将使程序的占用空间更小)。 否则,它应该是非静态的。

静态方法只允许访问静态成员。

参考

https://snailclimb.gitee.io/javaguide/#/docs/java/basic/final,static,this,super?id=final-%e5%85%b3%e9%94%ae%e5%ad%97



学习笔记      JAVA随笔

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!