static关键字
这个关键字表示静态的,用于不同地方意思不一样
静态字段
如果我们将其作用到字段上,那么该字段为类所拥有,我们使用new关键字创建出来的对象会共享这个这段。使用static标记字段之后我们也可以使用 类名.静态字段名的方式直接进行访问
public class StaticAndFinal {
public static String tip = "我是静态字段";
public static void main(String[] args) {
System.out.println(StaticAndFinal.tip);
}
}
静态方法
类似的,我们也可以将static作用到方法上,作用到方法上就表示该方法是为类所拥有,可以使用 类名.方法名进行调用。可以认为静态方法就是一个没有this参数的方法。注意在静态方法里面不能够访问类的实例字段和方法,换言只就只能够访问静态字段和静态方法
public class StaticAndFinal {
public static String tip = "我是静态字段";
private String tip1 = "我是普通字段";
public static int add(int a, int b) {
System.out.println(tip); // OK
System.out.println(tip1); // Error
return a + b;
}
public static void main(String[] args) {
int add = StaticAndFinal.add(1, 2);
}
}
上面代码在静态方法中就访问了tip1这个实例字段,这时IDEA就会提示如下
如果强制编译,那么程序就会出现以下错误
静态代码块
静态代码块在类加载的时候只会执行一次,里面常常执行对静态字段的初始化工作。(注意:不需要创建该类的对象,只要用到该类,那么静态代码块就会执行且只执行一次)。如果是通过new第一次访问对象,那么静态代码块会比代码块还要构造器先执行
public class StaticAndFinal {
public static int count;
static {
count++;
}
public static void main(String[] args) {
System.out.println(StaticAndFinal.count);
}
}
上面代码输出为1
静态内部类
静态内部类就是使用static修饰的一个内部类
class Animal{
static class Cat{
}
}
上面的Cat就是一个静态内部类
对于静态内部类,我们可以不用创建外部的实例,而直接创建内部静态内部类
public static void main(String[] args) {
Animal.Cat cat = new Animal.Cat();
}
对于外部类和静态内部类可以相互访问静态变量和方法,静态内部类可以直接通过字段名或者方法名访问外部类中的static字段、方法,如果出现命名冲突,那么就需要使用外部类名.静态字段(方法)进行访问。对于外部访问内部的静态字段、方法,那么必须使用静态内部类.静态字段(方法)进行访问
class Animal {
public static String tip = "外部静态字段";
//访问静态内部类静态变量
public int age = Cat.age;
static class Cat {
public String name;
public static int age;
public void t() {
// 访问外部类静态变量
System.out.println(tip);
}
}
}
上面代码t方法中的tip也可以写为 Animal.tip。对于静态内部类,我们简单一点理解就是静态内部类和外部类没有关系即可,都只能互相访问静态字段和方法,静态内部类的创建并不需要外部类的实例化。
final关键字
final字段
使用final修饰的字段就表示只能初始化一次,后面不能再被修改。
对于局部变量使用final修饰,我们可以后序再进行赋值
public static void main(String[] args) {
final int a;
a = 1;
// a = 2; // 再次赋值会抱错
System.out.println(a);
}
对于类的字段使用final修饰,必须在定义的时候就进行赋值
class A{
public final double PI;
}
上面代码没有赋值,IDEA提示以下信息
对于final字段的初始化,下面3种写法都可以
class A{
// 直接赋值
public final double PI = 3.14;
}
class A {
// 代码块初始化
public final double PI;
{
PI = 3.14;
}
}
class A {
// 构造器初始化,我们需要在所有声明的构造器中都进行初始化
public final double PI;
A(double pi) {
PI = pi;
}
public A() {
PI = 1;
}
}
final方法
使用final修饰的方法表示不能被重写
class A {
public final void show() {
System.out.println("A---show");
}
}
class B extends A {
@Override
public final void show() {
System.out.println("B---show");
}
}
上面的B继承了A,并且重写了A类中的show方法,但是A类中show方法使用final修饰,这时,编译器提示以下信息
final类
final类就表示不能够被继承
final class A {
}
class B extends A {
}
上面代码IDEA提示如下
需要说明的是,如果一个类声明为final,那么里面的所有方法自动成为final,但是字段并不会。