关键字this---static---final

  this和static都是java的关键字,它们用来表示一种数据类型,不能用做变量名,方法名,包名,参数。

1.this关键字

(1)this是一个引用,总是指向当前对象 

class Student {
	String name;
	int age;
	
	Student(){}
	Student(String name1,int age1){
		name = name1;
		age = age1;	
	}
	public void show(){
		System.out.print("name="+name+"----"+"age="+age);
	}

}

public class Person {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Student student = new Student("许巍",21);
		student.show();	
	}

}

  运行结果:

  name=许巍----age=21

下面我用内存图来讲解一下这个过程

以上边的代码为例子,讲解一下内存的加载:图中主要分为三块,左边的是栈,右边的是堆,下边的一大块是内存方法区

A.启动程序,Person.class的字节码文件(Person类编译后的文件)放到内存方法区中,执行main函数,main()进栈

B.创建student对象,会调用Stundent.class,Stundent.class放到内存方法区中.

C.在堆中创建对象会有默认值,age=0,name=null.因为创建对象时,传入了(“许巍”,21)---->age=21,name="许巍"

D.堆中的对象有内容首地址,Student的内存首地址为0x456,将此地址给student,student指向堆中的new Student(“许巍”,21)

E.调用show(),show函数有默认this,被省略了。

System.out.print("name="+this.name+"----"+"age="+this.age);

(2)局部变量和成员变量同名


 运行结果:

    前者name=null----age=0

    后者name=许巍----age=21

来分析以下原因:

局部变量和成员变量同名时,成员变量无效

Student类的成员变量与有参构造函数Student(String name,int age)的局部变量同名,成员变量无效。

(3)构造函数相互调用

 运行结果:

    前者:

      name=null----age=0
      name=许巍----age=21

    后者:name=许巍----age=21

来分析以下原因:

前者有参构造函数Student(String name,int age)调用this()<相当于调用Student()>,main()创建student对象,此时会在堆里创建对象,age=0,name=null(默认值),System.out.print()输出的值是:age=0,name=null

    参数传进后,age=21,name="许巍",调用show(),输出age,name变为传进的值。但是this()必须在构造函数的第一行,在其它位置会报错!

后者无参构造函数Student()调用this(String name,int age)<相当于调用Student(String name,int age)>,main()创建student对象,此时会在堆里创建对象,age=0,name=null(默认值),参数传进后,age=21,name="许巍",调用show(),输出age,name变为传进的值。但是this()必须在构造函数的第一行,在其它位置会报错!

2.static(静态的),修饰成员变量,成员函数

(1)static修饰的成员变量的特点:

  A.static修饰的成员变量是该类的所有对象共享 

  B.static修饰的成员变量是随着类的加载就在静态区中开辟了内存,所以优于非静态成员变量开辟内存

  C.static修饰的成员变量可以通过类名直接访问,也可以通过对象访问。

(2)静态成员与非静态成员变量的对比

  A.存储的数据:

         静态成员变量存储的是所有对象共享的数据

   非静态成员变量存储的是每个对象特有的数据

  B.存储的位置:

   静态成员变量是随着类的加载就在方法区中的静态区中开辟了内存

   非静态成员变量是随着对象的创建在堆中开辟内存

  C.调用方式:

   静态成员变量可以通过类名直接访问,也可以通过对象访问。

   非静态成员变量只能通过对象访问

  D.生命周期:

   静态成员变量随着类的加载就在方法区的静态区出现,整个程序执行完才消失(占用内存比较长,也是其缺点)

   静态成员变量随着对象的创建在堆中出现,随着对象被垃圾回收而消失

(3)修饰成员变量,成员函数

  A.什么时候把成员变量修饰为static?

    当成员变量被类的所有对象共用时

  B.什么时候把成员函数修饰为static?      

    当静态函数没有用到其所属类的所有非静态成员时

class Student {
    String name;//实例成员变量
    static String country = "CN";//类变量
    
    //非静态方法既可以使用静态变量,也可以使用非静态变量
    public void show(){//实例成员函数
        System.out.print(name+"----"+country);
    }
    
    //静态方法只能使用静态变量
    public static void fun(){//类方法
         
      //System.out.print(country);//无法从静态上下文中引用非静态变量name
      System.out.print(country);//可以从静态上下文中引用静态变量country
     } 
}

public class Person { public static void main(String[] args) {
 // TODO Auto-generated method stub 
  Student student = new Student(); 
  student.name = "王涛"; 
  student.show();
  
  Student student1 = new Student(); 
   student1.name = "萧泰"; 
    student1.fun(); 
  }
}

  运行结果:

  王涛----CN

  萧泰----CNCN

  分析一下为何在静态方法中只能用静态变量:

      fun()是个静态方法,name是非静态变量,需要在对象创建的时候才分配内存,而fun(),country在类加载的时候就分配内存存在了,此时使用name,name不存在。所以在静态方法中只能使用静态变量。

3.main函数

public class Person {
	/**
	 * main:一个函数,被JVM识别,程序运行的入口
	 * public:修饰符
	 * @param args:一个字符串函数类型的参数,其值由JVM传递
	 * static:静态,随着类的加载在内存静态方法区开辟内存
	 * void:无返回值
	 * 
	 */
	public static void main(String[] args) {
		System.out.print(args);
		System.out.print("---"+args.length);
		Student student = new Student();
		
	}

  运行结果:

    [Ljava.lang.String;@5f4fcc96---0

[:代表一维数组,[[:代表二维数组,java.lang.String:代表String类型,L:代表对象

4.final

  (1)修饰类,这个类不能被继承。

  (2)修饰方法,这个方法不能被重写

  (3) 修饰变量(局部变量,成员变量),此变量就是一个常量,一旦初始化,就不能再被赋值

 1 //TestA被final修饰,不能再被继承
 2   final class TestA{}
 3 
 4   //TestB继承TestA,会报错
 5   class TestB extends TestA{}
 6 
 7   //TestC被final修饰,不能再被继承
 8   class TestC{
 9     //show被final修饰,不能被重写
10     public final void show(){}
11   }
12 
13   //TestD继承TestA,会报错
14   class TestD extends TestC{
15     public final void show(){
16       //此处报错
17     }
18   }
19 
20 
21   public class Test {
22     final int a = 1;
23     //a = 2; 全局变量已被赋值为1,不能再被赋值
24 
25     public static void main(String[] args) {
26 
27 
28     }
29 
30   }
原文地址:https://www.cnblogs.com/langdon/p/6292102.html