Static关键字
定义: 可以在没有创建对象的时候进行某些操作,可以修饰成员变量和方法,也可以用作静态代码块。
静态成员: 1.静态成员变量是属于类的,在类初次被加载时被初始化,在类销毁时回收。2.这个类的所有实例化对象都共享同样的静态资源,所以只要有一个对象对静态成员进行了修改,静态成员的值对于所有对象都进行改变。3.静态成员在类加载时就创建存在,比对象更优先存在,存放在JavaHeap的静态存储区。
调用方式: 类名或方法名。
代码例子:
public class Test {
// 定义一个静态变量i,和一个非静态变量j
static int i;
int j;
public static void main(String[] args) {
//实例化两个不同的对象test1和test2
Test test1 = new Test();
Test test2 = new Test();
//用test1对象对静态变量i和非静态变量j赋值
test1.i = 1;
test1.j = 1;
//打印输出未被对象test2修改的静态变量i和非静态变量j的值
System.out.println("test2对象修改前的test1的静态成员i : " + test1.i + " test2对象修改前的test1的非静态成员j : " + test1.j);
//用test2对象对静态变量i和非静态变量j进行赋值
test2.i = 2;
test2.j = 2;
//打印输出被对象test2修改后的test1对象的静态变量i和非静态变量j的值和test2对象的静态变量i和非静态变量j的值
System.out.println("test2对象修改后的test1的静态成员i : " + test1.i + " test2对象修改后的test1的非静态成员j : " + test1.j);
System.out.println("test2的静态成员i : " + test2.i + " test2的非静态成员j : " + test2.j);
}
}
注: 在调用静态变量时可以试用对象名调用如 : test1.i, 但编译器会报 The static field Test.i should be accessed in a static way. 的警告,所以最好还是使用类名进行调用如 : Test.i。
输出结果为:
从输出结果可以看出test1对静态变量i赋的值1被test2的赋值改变了,所以test1对象和test2对象的静态变量i输出一样的值。而非静态变量j的值则没有改变,这是因为静态变量是属于类的,所以每个对象调用的都是一个静态变量。而非静态变量则因为对象的不同而存储空间不同。
静态方法: 1. 静态方法是属于类的,在类初次被加载时被初始化,在类销毁时回收。2.静态方法中可以直接访问静态成员,但不可以直接访问非静态成员,需要通过实例化一个对象然后通过对象名调用。3. 静态方法也优先于对象,所以在对象实例化前,类中的静态方法就可以使用。
调用方法:类名,方法名或直接方法名。
代码例子:
public class Test {
// 定义一个静态变量i,和一个非静态变量j。
static int i;
int j;
public static void main(String[] args) {
// 在没有实例化对象时调用静态方法。
Test.staMethod();
}
public static void staMethod() {
// 静态变量可以直接在静态方法中调用。
i = 3;
// 非静态变量要先实例化一个对象才能在静态方法中通过对象名调用。
Test test1 = new Test();
test1.j = 5;
System.out.println("我是静态方法的输出。静态变量i的值是 : " + i + " 非静态变量j的值是 : " + test1.j);
}
}
输出结果为:
输出结果显示在没有实例化对象的情况下静态方法可以被调用,静态变量可以在静态方法中直接调用,非静态变量需要现在静态方法中实例化一个对象,然后通过对象名调用。静态变量i的值和非静态变量的j的值都可以输出。
static方法不能被子类重写, 但如果子类中有一个名称和参数列表完全相同的方法,编译器不会报错,因为编译器会认为这是对父类方法的隐藏而不是重写。
静态代码块: 静态代码块是在类中的带static的代码块,不能定义在方法中,在类初次被加载时被初始化,在类销毁时回收。
具体的可以看我之前写的这篇博文:
JAVA之普通代码块、静态代码块和构造代码块
Super关键字
定义: super代表父类的引用,可以访问父类的成员方法,成员属性和构造方法。不能在静态方法中调用。
super调用父类的构造方法时一定在第一行。
代码例子:
public class Subject {
public String subjectName;
public int subjectNum;
public String subjectCategory;
Subject(){
System.out.println("这是父类的无参构造方法。");
}
Subject(int i){
System.out.println("这是父类的带参构造方法。");
}
public void subjectMethod() {
System.out.println("这是父类的方法输出。");
}
}
public class Science extends Subject {
Science() {
// 子类的构造方法执行之前会默认先执行父类的无参构造方法,这里用super关键字可以调用父类的带参构造方法。
super(3);
System.out.println("这是子类的构造方法。");
}
public void scienceMethod() {
// 子类用super关键字调用父类的方法和属性。
super.subjectMethod();
super.subjectNum = 18;
System.out.println("这是子类的方法输出。");
}
public static void main(String[] args) {
// 实例化子类对象。
Science science = new Science();
science.scienceMethod();
}
}
输出结果为:
输出结果显示子类在实例化时没有调用默认的父类无参构造方法,而是通过super调用了父类的带参构造方法。子类也通过super关键字调用了父类的成员方法和成员属性。
This关键字
定义: 代表指向当前对象的一个引用。可以用来访问当前对象的成员方法,成员属性和构造方法。不能在静态方法中调用。
this调用当前对象的构造方法时一定在第一行。
代码例子:
public class ThisTest {
int i;
ThisTest() {
// 在当前对象的无参构造方法中用this关键字调用带参构造方法。
this(1);
System.out.println("这是无参构造方法。");
}
ThisTest(int x) {
System.out.println("这是带参构造方法。");
}
public void thiMethod(int i) {
// 在方法中用this关键字调用当前对象的成员变量。
this.i = 5;
System.out.println("方法调用this关键字输出成员变量i的值为 : " + this.i);
}
public static void main(String[] args) {
ThisTest thiTest = new ThisTest();
// 调用输出方法。
thiTest.thiMethod(3);
}
}
输出结果为:
输出结果显示无参构造方法在执行前因为使用了this关键字所以执行了带参构造方法。在运行成员方法时因为使用了this关键字调用成员变量,所以输出的是成员变量的值而不是在调用方法时传入的参数值。