java学习笔记7——static和final关键字

时间:2022-11-28 16:52:00
这一篇是对剩下的一下java概念进行补充,对一些知识进行讲解。

一、static关键字

在《thinking in java》中对于static有这么一句话:

通常来说,当创建类时,就是在描述那个类的对象的外观与行为。除非用new创建那个对象,否则,实际上并未获得任何对象。执行new来创建对象的时候,数据存储空间才被分配,其方法才供外界调用。有两种情形用上述方法是无法解决的。一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少个对象,甚至根本不需要创建任何对象。另一种情形是,希望某个方法不与包含他的类的任何对象关联在一起。

  通俗的来讲,就是说当一个类被创建的时候,并不能说创建了一个对象,对象是需要被new出来的。 而没有创建对象,也是可以使用类中的方法的。
  这个时候,就要引入static关键字了,他的作用主要是创建出独立于类的方法和属性参数,可以进行使用。
那么static的作用范围是什么呢,被他修饰的会有什么效果呢?
static的修饰范围是:变量,方法和类。下面我们一个个说下去。

1、变量。

被static修饰的变量我们成为静态变量,看下面程序:

public class Demo {
static int i = 0;
public static void main(String[] args) {
Demo demo1 = new Demo();
System.out.println(demo1.i);
i++;
Demo demo2 = new Demo();
System.out.println(demo2.i);
}
}

结果:

0
1

  可以看出,当new了一个新的demo对象的时候,i并没有被初始化,而是继续被使用,可见,被static修饰的变量是独立于对象以外的。这里需要注意一点的就是加载顺序,这里先卖个关子,后面会进行解答。

2、方法。

static也可以修饰方法,被static修饰的方法有以下几个特点:
● 它们仅能调用其他的static 方法。
● 它们只能访问static数据。
● 它们不能以任何方式引用this 或super。

java学习笔记7——static和final关键字
  如上图所示,main方法是一个静态方法,被static修饰,它只能只用静态变量和静态方法,不然就会报错。同样的,this这些关键字也不能在static里面使用。
  一般含有static的方法都是写在工具类中,直接拿(类名.方法名)进行调用

3、类。

static是不能修饰外部类的,只能修饰内部类
  内部类:就是在一个类里面的创建的有一个类。我们知道外部类的名字必须是和类文件名是一样的,内部类的类名不需要和外部类一样。
看下列代码:

public class Demo {
static class test1 {
public test1() {
System.out.println("我是静态内部类方法");
}
}
public static void main(String[] args) {
new Demo.test1();
}
}

  可见,调用静态内部类的时候,不需要对外层的类进行实例化,就可以直接调用内部类。就是说不用先new一个Demo,然后再去调用test1,可以直接 new Demo.test1();
  那么,static的加载顺序是怎么样的呢,为什么static修饰方法,变量可以独立于类存在呢?
  在这里,我们引入一个代码块的概念:代码块就是写在内里面的,用大括号括起来的一部分代码,看下面代码:
java学习笔记7——static和final关键字
大家请看,如果不用{},这是错误的,static也可以用来修饰代码块。
那么问题来了:

public class Demo {

{
System.out.println("我是demo的内部代码块");
}

static {
System.out.println("我是demo的内部静态代码块");
}

public Demo() {
System.out.println("我是demo的构造方法");
}

static class test3 {
{
System.out.println("我是test3的内部静态类代码块");
}
static {
System.out.println("我是test3的内部静态类的静态代码块");
}
public test3() {
System.out.println("我是test3内部静态类的构造方法");
}
}
}
public class Test extends Demo {
static {
System.out.println("我是test方法的静态代码块");
}

public Test() {
System.out.println("我是Test方法的构造方法");
}

public static void main(String[] args) {
new Test();
new Demo();
new Demo.test3();
}
}

这段代码的运行结果是什么呢?
结果是:

我是demo的内部静态代码块
我是test方法的代码块
我是demo的内部代码块
我是demo的构造方法
我是Test方法的构造方法
我是demo的内部代码块
我是demo的构造方法
我是test3的内部静态类的静态代码块
我是test3的内部静态类代码块
我是test3内部静态类的构造方法

如果把new Test()注释掉呢?
结果:

我是demo的内部静态代码块
我是test方法的静态代码块
我是demo的内部代码块
我是demo的构造方法
我是test3的内部静态类的静态代码块
我是test3的内部静态类代码块
我是test3内部静态类的构造方法

总结一下,可以得出这样子的结论:

1. 在运行程序的时候,哪怕对象没有new,当类中有静态代码块,静态代码块会执行。(其实这也可以解释static修饰的方法或者参数是不需要通过对象去调用的,在程序运行的时候就已经就绪了)
2. 当程序内new对象时,首先运行的是对象类中的代码块,然后才是类的构造方法。
3. static修饰的代码块总比没有用static修饰的先运行
4. 当父类中含有static修饰的代码块时候,先运行父类的,再运行子类的

  所以,static关键字还是很有用的,在初始化程序的时候,不过编程的时候大家也要注意,避免用错地方。如果想了解static内部是如何实现的,可以查看jvm虚拟机的实现方式,这里就不说了,有兴趣的同学可以自己看。

二、final关键字

  final也可以修饰类,方法,变量。final有最后最终 的意思,顾名思义,这是一个最后结果,是不能被更改的。具体如下:

1、变量。

用final修饰的变量,是不能被更改的,如下
java学习笔记7——static和final关键字
会产生错误。而且,因为finla修饰的参数无法更改,即无法进行数据操作,所以要给其赋予初始值。

2、方法。

用final修饰的方法不能被重写。看如下代码:

public class Demo {
public final void fun1() {
System.out.println("我是用final修饰的方法");
}
public void fun2() {
System.out.println("我是方法");
}
}

java学习笔记7——static和final关键字
如上,方法不能被重写(override)

3、类

被final修饰的类,不能被继承
java学习笔记7——static和final关键字
java学习笔记7——static和final关键字
如上,无法被继承。

综上所述:

1. final修饰参数,参数值无法更改
2. final修饰方法,方法无法重写
3. final修饰类,类无法继承

最后,增加一个final的小知识:
看下面的代码,这是没有编译过的
java学习笔记7——static和final关键字
这是编译成.class文件以后又反编译回来的
java学习笔记7——static和final关键字
  可见,用final修饰的参数在编译后就直接进行使用了,类似于C语言里面的宏定义,而不使用final的还是使用参数表示,这也是java对final的一个定义知识点。大家可以了解一下。