您的位置:首页 > 编程语言 > Java开发

I学霸官方免费教程十:Java基础之关键字static和this

2015-08-10 17:57 106 查看

关键字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 = 10
cbd2.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调用构造方法时,只能在构造方法中调用,而且调用时必须写在构造方法中的第一行;构造方法不能自己调用自己,不能相互调用

版权声明:本文为博主原创文章,未经博主允许不得转载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: