一、静态属性
static是Java中常用的关键字,代表“全局”或者“静态”的意思。关于static的特征,可以理解为:方便在没有创建对象的情况下来进行某些操作。通常可用于修饰成员变量和方法,也可以形成静态代码块。
实际应用中,可将需频繁操作、通用型信息设置、公共组件封装等操作设置为“静态”。
应用一:static+成员变量 vs 成员变量
概念:
静态成员:用static修饰的成员变量,通常也成为静态成员、静态属性、类成员、全局属性等。
非静态成员:没有被static修饰的成员变量,也称为叫做非静态成员、实例变量,实例成员,对象成员、对象属性等。
特征:
静态成员:
- 静态成员是属于整个类的,由类所进行维护,仅在类初次加载时会被初始化,在类销毁时回收。
- 通过该类实例化的所有对象都共享类中静态资源,任一对象中信息的修订都将影响所有对象。
- 由于静态成员在类加载期间就已经完成初始化,存储在Java Heap(JDK7.0之前存储在方法区)中静态存储区,因此优先于对象而存在,可以通过类名和对象名两种方式访问。
非静态成员:
- 非静态成员属于对象独有,每个对象进行实例化时产生各自的成员,随着对象的回收而释放。
- 对象对各自成员信息的修订不影响其他对象
- 只能通过对象名访问。
应用:
可以将频繁调用的公共信息,期望加快运行焦虑的成员设置为静态。但需注意,由于其生命周期长,即资源占用周期长,要慎用。
示例:
定义国产车类CarDemo,分别包含静态属性firm,对象属性color、price
定义测试类CarTest,针对CarDemo进行测试
备注:暂不考虑属性的范围权限
public class CarDemo{
static String firm;//厂商
String color;//颜色
int price;//价格
public CarDemo(String color,int price){
this.color = color;
this.price = price;
}
//信息展示方法
public void display(){
//类内静态成员访问方式1:类名.成员名
System.out.println("本款汽车信息展示:厂商--"+CarDemo.firm+",颜色--"+this.color+",价格--"+this.price);
//类内静态成员访问方式2:this.成员名
System.out.println("本款汽车信息展示:厂商--"+this.firm+",颜色--"+this.color+",价格--"+this.price);
//类内静态成员访问方式3:成员名
System.out.println("本款汽车信息展示:厂商--"+firm+",颜色--"+this.color+",价格--"+this.price);
}
}
public class CarTest{
public static void main(String[] args){
//类外静态成员访问方式1:类名.成员名
CarDemo.firm = "一汽集团";
CarDemo one = new CarDemo("蓝色",200000);
one.display();
CarDemo two = new CarDemo("红色"1500000);
two.display();
//类外静态成员访问方式2:对象名.成员名
two.firm = "上汽集团";
one.display();
}
}
此时输出结果为:
本款汽车信息展示:厂商--一汽集团,颜色--蓝色,价格--200000
本款汽车信息展示:厂商--一汽集团,颜色--红色,价格--150000
本款汽车信息展示:厂商--上汽集团,颜色--蓝色,价格--200000
总结:
- 类外可应用“类名.成员名"或“对象名.成员名“的方式访问非私有静态成员,更推荐用”类名.成员名“体现其特性。应用”对象名.成员名“时会出现警告,但不影响程序运行。
- 类内可应用”类名.成员名“或”this.成员名“的方式访问,应用”this.成员名“时会出现警告,但不影响程序运行。
二、静态方法
应用二:static+成员方法 vs 成员方法
概念:
静态方法:用static修饰的成员方法,通常也成为静态方法、类方法、全局方法等。
非静态方法:没有被static修饰的成员方法,也称为叫做非静态方法、实例方法、对象方法等。
特征:
与静态成员相似,静态方法属于整个类的,由类所进行维护,因此可以通过类名和对象名两种方式访问,也因此在静态方法中无法直接访问同类中的非静态成员。
总结:
1、静态方法中可以通过“类名.成员“或”成员”的方式访问类内静态成员/静态方法
2、不允许直接访问本类中的非静态成员/非静态方法
3、可以通过实例化产生本类对象,通过“对象.成员“的方式访问类内非静态成员/非静态方法。
4、类外可应用“类名.成员方法“或”对象名.成员方法“的方式访问非私有静态方法
5、应用”对象名.成员方法“时出现警告,但不影响程序运行。
6、非静态方法可以通过“类名.成员名“或”成员“或者“this.成员“的方式访问内静态成员/静态方法
7、应用”this.静态成员/静态方法“时会出现警告,但不影响程序运行。
8.不允许在方法内部定义静态局部变量。
三、静态代码块
应用三:static+代码块 vs 代码块
概念:
静态代码块:被static修饰的,定义在类内部,有{}括起来的代码段。
构造代码块:没有被static修饰的,定在在类内部,有{}括起来的代码段。
普通代码块:定在在方法内部,用{}扩起的代码段。
特征:
静态代码块:
- 只能出现在类内,不允许出现在方法内。
- 可以出现多次,按顺序在类加载时执行。
- 无论该类实例化多好对象,只执行一次。
构造代码块:
- 可以在类内出现多次,按顺序在每个对象实例化时执行。
- 执行优先级:晚于静态代码块,高于构造方法。
- 每次执行对象实例化时,均会执行一次。
普通代码块:
- 可以在方法内出现多次,按顺序在方法调用时执行。
应用:
静态代码块:基于性能优先的考虑,多适用于需要在项目启动时执行一次的场景,譬如项目资源整体加载等。
构造代码块:多适用于类中每个对象产生时都是需要执行的功能封装。与构造方法的区别在于,构造方法时在new执行时有选择性的调用带參或者无參构造,而构造代码块则是,在每个对象实例化都一定会执行。
普通代码块:适用于在方法内进行代码功能拆分。
示例:
定义国产车类CarDemo,包含静态成员firm,非静态方法run;定义测试类CarTest,针对CarDemo进行测试。
备注:此处不考虑属性的访问权限
- 当CarDemo类在静态代码块和构造代码块中分别对静态成员赋值,并添加构造方法
public class CarDemo{
static String firm;//厂商
static{
firm = "一汽";
System.out.println("我是静态代码块");
}
{
firm = "东风";
System.out.println("我是构造代码块");
}
public CarDemo(){
System.out.println("我是构造方法");
}
public void run(){
System.out.println("本款汽车信息展示:厂商--"+CarDemo.firm);
}
}
测试类CarTest中实例化CarDemo,并调用run方法
public class CarTest{
public static void main(String[] args){
CarDemo one = new CarDemo();
one.run();
System.out.println("*****************");
CarDemo two = new CarDemo();
two.run();
}
}
运行结果:
我是静态代码块
我是构造代码块
我是构造方法
本款汽车信息展示:厂商--东风
**************************
我是构造代码块
我是构造方法
本款汽车信息展示:厂商--东风
总结:
1、执行优先级:静态代码块>构造代码块>构造方法
2、执行次数:静态代码块只执行1次;构造代码块、构造方法随对象实例化个数而定
- CarDemo类中添加成员属性color,并在静态代码块和构造代码块中分别对color进行赋值时
public class CarDemo{
static String firm;
String color;
static{
firm = "一汽";
color = "蓝色";//错误提示:不能在静态块中操作非静态成员
System.out.println("我是静态代码块");
}
{
firm = "东风";
color = "蓝色";
System.out.println("我是构造代码块");
}
}
总结:
1、不能在静态代码块中直接对非静态成员赋值
2、可以在构造代码块中直接操作静态和非静态成员。
- 当将属性定义移入静态代码块时
public class CarDemo{
static{
static String firm = "一汽";//错误提示:不允许在静态代码块中声明静态成员;
String color = "蓝色";
System.out.println("我是静态代码块");
}
{
firm = "东风";//错误提示:无法在构造代码块中访问到相关成员
color = "红色";
System.out.println("我是构造代码块");
}
}
总结:
1、不能在静态代码块声明静态成员,可以声明局部变量。
2、静态代码块中声明的变量,在外部无法进行访问。
- 当在run方法中分别添加2个代码块时
public class CarDemo{
public void run(){
int sum = 10;
System.out.println("我是普通代码块1:"+sum);
}
{
int sum = 20;
System.out.println("我是普通代码块2:"+sum);
}
}
public class CarTest{
public static void main(String[] args){
CarDemo one = new CarDemo();
one.run();
}
}
运行结果为:
我是普通代码块1:10
我是普通代码块2:20
- 当在两个代码块上部添加同名局部变量声明时:
public class CarDemo{
public void run(){
int sum = 50;
{
int sum = 10;//错误提示:不允许定义重名变量
System.out.println("我是普通代码块1:"+sum);
}
{
int sum = 20;
System.out.println("我是普通代码块2:"+sum);
}
}
}
总结:
1、普通代码块在方法内顺序执行,各自作用范围独立。
2、方法内定义的局部变量,作用范围为:自定义位置起,至方法结束。在此期间,不允许方法中普通代码块内存在局部变量的声明。