目录
static final(等价于final staic,但是一般习惯staic在前)
final可以修饰属性,方法,类,局部变量(静态变量、实例变量和局部变量);
其中,final修饰的属性表明是个常量,它的初始化可以在编译期,也可以在运行期,初始化后不能被改变;
final修饰的属性跟具体对象有关,在运行期初始化的final属性,不同对象可以有不同的值;
final修饰的方法不能被子类方法覆盖,但可以被继承;
private不能被子类方法覆盖,private类型的方法默认是final类型的
final修饰的类不能被继承,没有子类,final类中的方法默认是final的
final不能用于修饰构造方法;
另外,对于基本类型数据,final会将值变为一个常数(创建后不能被修改);但是对于对象句柄(亦可称作引用或者指针),final会将句柄变为一个常数(进行声明时,必须将句柄初始化到一个具体的对象。而且不能再将句柄指向另一个对象。但是,对象的本身是可以修改的。这一限制也适用于数组,数组也属于对象,数组本身也是可以修改的。方法参数中的final句柄,意味着在该方法内部,我们不能改变参数句柄指向的实际东西,也就是说在方法内部不能给形参句柄再另外赋值)。
static表示“全局”或者“静态”的意思,可以用来修饰:属性,方法,代码段,内部类(静态内部类或嵌套内部类),static不可以修饰局部变量。
其中,static修饰的属性的初始化在编译期(类加载的时候),初始化后能改变,并且每个对象都只有一个值,主要强调它们只有一个。
static修饰的属性、方法、代码段跟该类的具体对象无关,不创建对象也能调用static修饰的属性、方法等,
static和“this、super”势不两立,因为this、super正好跟具体对象有关。
也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
用public修饰的static属性和方法本质是全局变量和全局方法,当声明它类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。
其中:
- 类成员变量
- 静态变量(类变量): static修饰
- 实例变量 : 无static修饰
- 局部变量 :(方法内部声明)
static修饰的属性强调它们只有一个,final修饰的属性表明是一个常数(创建后不能被修改)。static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问。static final也可以修饰方法,表示该方法不能重写,可以在不new对象的情况下调用
在类中,可以将某一块代码声明为静态的,这样的程序块叫静态初始化段。静态代码块的一般形式如下:
1 //静态代码块
2 static {
3 语句序列
4 }
5
6 //普通代码
7 {
8 语句序列
9 }
其中,静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面。
静态代码块里面的变量都是局部变量,只在本块内有效。
静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类。
一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行。
静态方法只能访问静态成员,实例方法可以访问静态和实例成员。之所以不允许静态方法访问实例成员变量,是因为实例成员变量是属于某个对象的,而静态方法在执行时,并不一定存在对象。同样,因为实例方法可以访问实例成员变量,如果允许静态方法调用实例方法,将间接地允许它使用实例成员变量,所以它也不能调用实例方法。基于同样的道理,静态方法中也不能使用关键字this。main()方法是一个典型的静态方法,它同样遵循一般静态方法的规则,所以它可以由系统在创建对象之前就调用。
例子1:
1 public class staticBlock{
2 //定义一个普通的main()方法
3 public static void main(String args[]){
4 System.out.println("This is main method.");
5 }
6 //定义一个静态代码块
7 static{
8 System.out.println("This is static block.");
9 int stVar = 0; //这是一个局部变量,只在本块内有效
10 }
11 }
运行结果:
1 2 |
|
从以上输出结果中可以看出,静态代码块甚至在main方法之前就被执行。在main()方法中可以完成的任务在静态代码块中都可以完成。但是二者在执行上仍然有一些区别。
例子2:
1 public class staticBlock{
2 static int stMember = 100; //定义静态成员变量
3 public static void main(String args[]){
4 System.out.println("This is main method.");
5 }
6 //第一个静态代码块
7 static{
8 System.out.println("This is first static block.");
9 stMember = 200; //访问静态成员变量
10 staticBlock oa = new staticBlock(); //创建对象
11 System.out.println("stMember = " + oa.stMember);
12 statFun(); //调用静态方法
13 }
14 //定义一个静态方法
15 static void statFun(){
16 System.out.println("This is a static method.");
17 }
18 //第二个静态代码块
19 static{
20 System.out.println("This is second static block.");
21 }
22 }
运行结果如下:
1 2 3 4 5 |
|
静态代码块与普通代码块的差异如下:
相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,
一般在代码块中对一些static变量进行赋值。
例子:
1 //普通类
2 public class PuTong {
3 public PuTong(){
4 System.out.print("默认构造方法!-->");
5 }
6
7 //非静态代码块
8 {
9 System.out.print("非静态代码块!-->");
10 }
11
12 //静态代码块
13 static{
14 System.out.print("静态代码块!-->");
15 }
16
17 public static void test(){
18 {
19 System.out.println("普通方法中的代码块!");
20 }
21 }
22 }
23
24 //测试类
25 publicclass TestClass {
26
27 /**
28 * 区别两次new静态与非静态代码块执行情况
29 */
30 public static void main(String[] args) {
31 PuTong c1 = new PuTong();
32 c1.test();
33
34 PuTong c2 = new PuTong();
35 c2.test();
36 }
37 }
/*
运行输出结果是:
静态代码块!-->非静态代码块!-->默认构造方法!-->普通方法中的代码块!
非静态代码块!-->默认构造方法!-->普通方法中的代码块!
*/
一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调用的时候,需要使用静态方法,这种代码是被动执行的.
两者的区别就是:静态代码块是自动执行的;
静态方法是被调用的时候才执行的.
作用:静态代码块可用来初始化一些项目最常用的变量或对象;静态方法可用作不创建对象也可能需要执行的代码.
可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类。静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner)。嵌套类从JDK1.1开始引入。其中inner类又可分为三种:
其一、在一个类(外部类)中直接定义的内部类;
其二、在一个方法(外部类的方法)中定义的内部类;
其三、匿名内部类。
1 public class StaticTest {
2 private static String name = "javaJohn";
3 private String id = "X001";
4 static class Person{
5 private String address = "swjtu,chenDu,China";
6 public String mail = "josserchai@yahoo.com";//内部类公有成员
7 public void display(){
8 //System.out.println(id);//不能直接访问外部类的非静态成员
9 System.out.println(name);//只能直接访问外部类的静态成员
10 System.out.println("Inner "+address);//访问本内部类成员。
11 }
12 }
13
14 public void printInfo(){
15 Person person = new Person();
16 person.display();
17 //System.out.println(mail);//不可访问
18 //System.out.println(address);//不可访问
19 System.out.println(person.address);//可以访问内部类的私有成员
20 System.out.println(person.mail);//可以访问内部类的公有成员
21
22 }
23 public static void main(String[] args) {
24 StaticTest staticTest = new StaticTest();
25 staticTest.printInfo();
26 }
27 }
在静态嵌套类内部,不能访问外部类的非静态成员,这是由Java语法中"静态方法不能直接访问非静态成员"所限定。若想访问外部类的变量,必须通过其它方法解决,由于这个原因,静态嵌套类使用很少。注意,外部类访问内部类的的成员有些特别,不能直接访问,但可以通过内部类来访问,这是因为静态嵌套内的所有成员和方法默认为静态的了。同时注意,内部静态类Person只在类StaticTest 范围内可见,若在其它类中引用或初始化,均是错误的。
1 public class Outer {
2 int outer_x = 100;
3 class Inner{
4 public int y = 10;
5 private int z = 9;
6 int m = 5;
7 public void display(){
8 System.out.println("display outer_x:"+ outer_x);
9 }
10 private void display2(){
11 System.out.println("display outer_x:"+ outer_x);
12 }
13 }
14 void test(){
15 Inner inner = new Inner();
16 inner.display();
17 inner.display2();
18 //System.out.println("Inner y:" + y);//不能访问内部内变量
19 System.out.println("Inner y:" + inner.y);//可以访问
20 System.out.println("Inner z:" + inner.z);//可以访问
21 System.out.println("Inner m:" + inner.m);//可以访问
22 InnerTwo innerTwo = new InnerTwo();
23 innerTwo.show();
24 }
25 class InnerTwo{
26 Inner innerx = new Inner();
27 public void show(){
28 //System.out.println(y);//不可访问Innter的y成员
29 //System.out.println(Inner.y);//不可直接访问Inner的任何成员和方法
30 innerx.display();//可以访问
31 innerx.display2();//可以访问
32 System.out.println(innerx.y);//可以访问
33 System.out.println(innerx.z);//可以访问
34 System.out.println(innerx.m);//可以访问
35 }
36 }
37 public static void main(String args[]){
38 Outer outer = new Outer();
39 outer.test();
40 }
41 }
以上代码需要说明有,对于内部类,通常在定义类的class关键字前不加public 或 private等限制符,若加了没有任何影响,同时好像这些限定符对内部类的变量和方法也没有影响(?)。另外,就是要注意,内部类Inner及InnterTwo只在类Outer的作用域内是可知的,如果类Outer外的任何代码尝试初始化类Inner或使用它,编译就不会通过。同时,内部类的变量成员只在内部内内部可见,若外部类或同层次的内部类需要访问,需采用示例程序中的方法,不可直接访问内部类的变量。
1 public class Outer {
2
3 private String outerName = "This is Outer Name";
4
5 public void test() {
6
7 for(int i=0;i<3;i++) {
8 class Inner {
9 public void display() {
10 System.out.println(outerName);
11 }
12 }
13 Inner inner = new Inner();
14 inner.display();
15 }
16 }
17 }
在上面的代码中,只能定义成class inner,不能定义成public class inner,因为此时是作为方法中的变量定义的,不是作为类的成员变量。
参考链接:
https://blog.csdn.net/qq_40665031/article/details/78440084
https://blog.csdn.net/hust_yfang/article/details/79585696
https://www.cnblogs.com/EasonJim/p/7841990.html
https://blog.csdn.net/leixiongbo/article/details/52161936
https://blog.csdn.net/WelcomeSpring/article/details/79430546