重新开始学Java——static与final修饰符

static 修饰符可以用来修饰类的成员变量、 成员方法、 代码块;用 static 修饰的成员变量表示静态变量, 直接使用类名来访问;用 static 修饰的成员方法表示静态方法, 直接使用类名来访问;用 static 修饰的代码块表示静态代码块, JVM 加载类时就会执行该代码块。

被 static 修饰的成员归类所有:它不依赖于类的特定实例, 被类的所有实例所共享;只要该类被加载, JVM 就能根据类名在方法区定位到它们。

static 变量(类变量):被 static 修饰的变量称为静态变量或类变量(类属性),类属性属于整个类。也就是说当系统第一次使用类时(类的准备阶段)即为该类属性分配内存空间, 类属性开始生效,直到该类被卸载, 该类的类属性所占的内存才被 JVM 的垃圾回收机制回收。

类属性的生存范围几乎等同于该类的生存范围:当类初始化完成后, 类属性也被初始化完成,当类被卸载, gc 才回收其所占的内存空间。

static 变量(类变量):可以通过类来访问 ( 即类名.类属性名)。当类初始化完毕后, 类属性也初始化完毕,所以可以通过类名访问类属性;也可以使用对象来访问 ( 即对象名.类属性名),使用对象名来访问类属性并不是访问该对象所具有的属性,当系统创建该类的对象时不会再度为类属性分配内存,也不会再度对类属性进行初始化。对象根本不包括其所属类的类属性:使用对象访问类属性是一种假象,本质上, 通过对象访问类属性还是要转换成使用类访问类属性。

静态变量和实例变量的区别:对于静态变量:运行时 JVM 只为其分配一次内存,(即在加载类的过程中完成静态变量的内存分配);静态变量可以通过类名直接访问;静态变量会被类的所有实例所共享。对于实例变量:每创建类的一个实例, 就会为实例变量分配内存;实例变量对于每个实例而言是专属的。

public class Sheep {
	public static String school = "大肥羊学校";
	private String name;// 实例属性(非静态属性)
		public String getName() {
	return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
public class TestSheep {
	public static void main(String[] args) {
		// 在加载类后 就创建了 school变量,并赋予相应的值(暂时的理解)
		// 只要用到school 那么就只有这么一份
		System.out.println(Sheep.school);
		// 创建Sheep 实例,并 为实例属性 name 开辟空间,赋予相应的默认值
		Sheep s = new Sheep();
		System.out.println(s.getName());
		s.setName("喜羊羊");
		 System.out.println(s.getName());
		// 创建Sheep 实例,并 为实例属性 name 开辟空间,赋予相应的默认值
		//s = new Sheep();// 栈中的变量,声明一次,可以接收不同的变量
		Sheep s2 = new Sheep();
		System.out.println(s2.getName());
		s2.setName("懒羊羊");
		System.out.println(s2.getName());
		Sheep s3 = null;
		System.out.println(s3.school);// 因为访问的是静态属性
	}
}

类的信息放在方法区中,就是所有的静态的东西都放在方法区中。方法的内容放在方法区中,代码公共部分放在方法区中。即使在堆区域不存放任何东西,那么静态的东西都放在方法去中,通过类名可以去访问。即使通过对象名进行访问类中的某一个属性的时候,那个属性也是存放在方法区中。

代码块

/**
* 一个类中可以包含:
* 属性:静态属性 和 实例属性
* 方法:静态方法 和 实例方法
* 构造:与类名同名、没有返回类型的特殊方法
* 代码块:静态代码块 和 普通代码块
* 在同一个类中,代码块的执行顺序,跟书写的顺序有关,谁在前谁先
执行
* 对于静态代码块,同一个类中谁先书写谁先执行
* 对于静态代码块,如果子类继承了父类,则所有的静态代码块按顺序
依次执行,先父类,后子类
* 等到所有的静态代码块执行完,如果构造了一个对象,则执行 普通代
码块
*/
public class Father {
	private String name = "张三丰";
	//protected String school;
	protected static String school;
	public Father(){
		System.out.println("Father:构造方法," + this.name);
	}
	{// 如果没有加上花括号,这样是错误的。注意,这里没有static修饰的代码块,就是普通代码块
		System.out.println("Father:我是普通代码块1");
		this.name = "张三丰";// 可以通过 代码块 对非静态属性进行初始化,也就是赋值
	}
	{// 如果没有加上花括号,这样是错误的。注意,这里没有static修饰的代码块,就是普通代码块
		System.out.println("Father:我是普通代码块A");
	}
	static{// 有static 修饰的代码块就是静态代码块,只执行一次
		System.out.println("Father:静态代码块1");
		//school = "学校"; // 静态代码块 只能访问静态属性
		 school = "学校";
	}
	static{// 有static 修饰的代码块就是静态代码块,只执行一次
		System.out.println("Father:静态代码块A");
	}
}
TestFather:
public class TestFather {
	public static void main(String[] args) {
		// 执行顺序:静态代码块、普通代码块、构造方法
		Father f1= new Father();
		Father f2= new Father();
	}
}
如果要有继承的话,有如下的例子:
public class Child extends Father{
	public Child(){
		super();
	}
	static {
		System.out.println("child 静态代码块");
	}
}
TestChild:
public class TestChild {
	public static void main(String[] args) {
		Child c1 = new Child();
	}
}

final 表示”不可修改的”, final 可以修饰非抽象类、 非抽象成员方法、 变量。 注: 被 final 修饰的类, 不能被继承, 没有子类, 比如 String 类;被 final 修饰的方 法不能被子类的方法覆盖;被 final 修饰的变量表示常量, 只能被赋值一次。不能使 用 final 来修饰构造方法,因为构造不可能被继承, 因此没有必要限制为最终的、 不 可更改的。

/**
 * 所有的 final 修饰的变量,不论静态、实例、还是局部变量,其取值都不能修改
*/
public class TestFinal1 {
	public static final double pi = 3.14;// 静态变量 pi 的值 不能再被修改
	public final int a = 100; // 实例变量 a 的值 不能再被修改该
	public static void main(String[] args) {
		// final 修饰局部变量
		final int a = 100;
		//a = 200; // The final local variable a cannot be assigned
		System.out.println("a = "+a);
		// 尝试修改 静态变量 的值
		//TestFinal1.pi = 6.28; // The final field TestFinal1.pi cannot be assigned
		TestFinal1 tf = new TestFinal1();
		// 尝试修改实例变量的值
		//tf.a = 200; // The final field TestFinal1.a cannot be assigned
		// 但是是可以使用的
		System.out.println(tf.a);
	}
}
final 修饰的类:
// 这个类是最终的,不可更改的一个类
public final class LuoZi {
 	private String name;
}
// The type XinLuoZi cannot subclass the final class LuoZi
public class XinLuoZi /* extends LuoZi */ {
}
final 修饰的方法:
public class Father {
	public void eat( String food){
		System.out.println("吃" + food);
	}
	public final void run( ){
		System.out.println("跑");
	}
}
public class Child extends Father{
	protected String name;
	public void eat(String food){
		System.out.println("wochi " + food);
	}
	// 尝试重写 继承自 父类的 final 修饰的分法
	// Cannot override the final method from Father
	// public void run(){
	// }
}

转载于:https://my.oschina.net/lujiapeng/blog/2253173

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值