关键字static
static:静态的,用于修饰类的成员;被static修饰的成员,在字节码文件(.class文件)被类加载器(Classloader)从硬盘加载到内存中时,就被在内存中创建。没有被static修饰的成员在使用关键字new创建对象后才被创建
被static修饰的成员,一个类只有一份,不属于某个对象,而且会常驻内存;
例如:地球属于全人类,而不属于某一个人。
静态属性的调用: 类名.属性名;
静态方法的调用: 类名.方法名();
静态块语法格式: static{ //代码 };class文件被加载的时候执行一次
在静态方法或静态块中直接调用类的属性,这个属性也必须是静态的
当静态的属性和静态块或静态方法在一个类中时,可以直接使用属性名来访问属性
实例:/**
* 演示关键字static的使用
* @author 学霸联盟 - 赵灿
*/
public class StaticDemo {
// 声明一个静态的属性name,并赋值为“张三”
static String name = "张三";
// 声明一个非静态的属性age,并赋值为1
int age = 18;
// 声明一个静态方法
static void staticMethod1(){
System.out.println("静态方法staticMethod1");
/*
* 这里可以直接使用静态成员name和staticMethod2
* 但是想要使用非静态成员age、method1和method2
* 就必须创建对象,再使用对象调用非静态的成员
*/
staticMethod2();
System.out.println("静态的属性name:" + name);
}
// 声明一个静态方法
static void staticMethod2(){
//这里可以直接调用静态成员
System.out.println("静态方法staticMethod2");
}
// 声明一个非静态方法
void method1(){
System.out.println("非静态方法method1");
//这里可以直接使用静态成员和非静态成员
method2();
// 普通属性必须使用对象调用
System.out.println("非静态的属性age:" + age);
}
// 声明一个非静态方法
void method2(){
System.out.println("非静态方法method2");
}
/*
* main方法是静态方法
* 静态方法中可以直接使用本类静态成员,也可以通过类名调用静态成员
* 但使用非静态成员时,无论是本来还是其他类,都要先创建对象
* 再通过对象去调用非静态的成员
*/
public static void main(String[] args) {
// 静态的成员可以直接使用类名.成员的方式调用,无需创建对象再调用
StaticDemo.staticMethod1();
// 创建一个Person类的对象p
StaticDemo sd = new StaticDemo();
sd.method1();
}
}
运行结果:
静态方法staticMethod1
静态方法staticMethod2
静态的属性name:张三
非静态方法method1
非静态方法method2
非静态的属性age:18
实例:/** * 演示普通代码块和静态代码块 * @author 学霸联盟 - 赵灿 */public class CodeBlockDemo { static int si = 1; int i = 1; //静态块:只会再该类的class文件被加载时执行一次 static{ //静态块中可以直接使用静态成员,但不能直接使用非静态成员 System.out.println("静态块被执行"); } //非静态代码块:创建一个对象,就会被执行一次 { //非静态块中可以直接使用静态成员,也可以直接使用非静态成员 System.out.println("普通代码块被执行"); } public static void main(String[] args) { //在main方法开始之前,静态块就已经执行 System.out.println("----- main方法开始 -----"); //未创建当前类的对象之前,就执行了静态块 System.out.println("si = " + si); //普通代码块,创建对象时被执行 System.out.println("----- 创建对象开始 -----"); /* * 创建一个对象时 */ CodeBlockDemo cbd1 = new CodeBlockDemo(); //输出结果:cbd1.si = 1 , cbd1.i = 1 System.out.println("cbd1.si = " + cbd1.si + " , cbd1.i = " + cbd1.i); //对静态属性si和非静态属性i都进行修改 cbd1.si = 10; cbd1.i = 10; System.out.println("----- 再次创建对象开始 -----"); CodeBlockDemo cbd2 = new CodeBlockDemo(); //输出结果:cbd1.si = 10 , i = 10 System.out.println("cbd1.si = " + cbd1.si + " , i = " + cbd1.i); //输出结果:cbd2.si = 10 , i = 1 System.out.println("cbd2.si = " + cbd2.si + " , i = " + cbd2.i); }}运行结果:静态块被执行----- main方法开始 -----si = 1----- 创建对象开始 -----普通代码块被执行cbd1.si = 1 , cbd1.i = 1----- 再次创建对象开始 -----普通代码块被执行cbd1.si = 10 , i = 10cbd2.si = 10 , i = 1由结果可以看出,静态的属性si一个类只有一份,两个对象cdb1和cdb2共同拥有这一份,任何一个对象对静态的属性进行修改,其他对象访问时也会随之改变。而非静态的属性i,则是每个对象各有一份,所以修改某一个对象的非静态属性,其他对象不会随之改变
关键字this
一个指向自身的引用(变量),他在哪个对象中,他的值就是哪个对象的地址。实例:/**
* 演示关键字this的使用
* @author 学霸联盟 - 赵灿
*/
public class ThisDemo {
// 声明一个变量a并赋值为123
public int a = 123;
/*
* 声明一个变量b并赋值为变量a的值,所以变量b的值也是123
* 创建一个对象执行一次
*/
public int b = this.a;
// 声明一个没有返回值,没有参数的方法print
public void print() {
// 声明一个局部变量a,局部变量和成员变量可以重名
int a = 456;
// 变量a前没用关键字this,代表使用的是局部变量a;输出的值是456
System.out.println(a);
// 变量a前使用了关键字this,代表使用的是成员变量a;输出的值是123
System.out.println(this.a);
// 由于没有局部变量和成员变量b重名,所以前面的this可以省略
System.out.println(b);
System.out.println("this的地址:" + this);
}
//静态的main方法
public static void main(String[] args) {
// new语句执行完,其中的变量a和b都有了值是123
ThisDemo td1 = new ThisDemo();
// 给对象td1的属性a赋值为789
td1.a = 789;
// 调用对象td1的print方法,此时ThisDemo类中使用的this都和td1中存储的地址相同
td1.print();
System.out.println("td1的地址:" + td1);
// 创建对象td2
ThisDemo td2 = new ThisDemo();
// 使用对象td2调用print方法,此时ThisDemo类中使用的this都和td2中存的地址相同
td2.print();
System.out.println("td2的地址:" + td2);
}
}
输出结果:
456
789
123
this的地址:cls.keyword.ThisDemo@659e0bfd
td1的地址:cls.keyword.ThisDemo@659e0bfd
456
123
123
this的地址:cls.keyword.ThisDemo@2a139a55
td2的地址:cls.keyword.ThisDemo@2a139a55
小结:
1、不能用在static修饰的成员中,因为this代表的是对象的引用2、如果在非静态的方法或非静态的代码块中,没有局部变量和属性(成员变量)重名,this可以省略;否则,必须使用 this.属性的方式来访问类的属性
3、调用本类的其他构造方法:this( [参数列表] )
使用关键字this调用构造方法时,只能在构造方法中调用,而且调用时必须写在构造方法中的第一行;构造方法不能自己调用自己,不能相互调用