关键字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 }