非访问修饰符static、final、abstract、synchronized 和 volatile

我们为什么需要这些非访问修饰符?

  像其他语言一样,Java可以使用修饰符来修饰类中方法和属性。主要有两类修饰符:

  四个访问修饰符,解决了Java中类与类之间访问权限的设置问题。而非访问控制修饰符,各有各的妙用,且听我一一道来:

static修饰符

  static 修饰符,可以用来修饰类方法和类变量。

static变量

  • 修饰变量时,称变量为静态变量:
    static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。

static方法

  • 修饰方法时,称方法为静态方法:
    static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。

  来个实例:

class Person {
	public static int totalnum;	 // totalnum为静态变量变量,static修饰
	private String name;
	private int age;

	Person(String name,int age) {
		this.name = name ;
		this.age = age;
		Person.totalnum++;
	}
	
	public void die(){
		totalnum--;
	}
	
	public static void destroy() {
		totalnum = 0;
		// age = 18;   会报错,static方法中不能使用非static变量
	}

}

public class Test {
	
   public static void main(String[] args){
	  Person person1 = new Person("小猪",18);
	  System.out.println("小猪出生后,人类总人数:"+person1.totalnum);  // Person.totalnum结果与一样
	  Person person2 = new Person("小牛",20);
	  System.out.println("小牛出生后,人类总人数:"+person2.totalnum);  // Person.totalnum结果与一样
	  person2.die();
	  System.out.println("小牛死亡后,人类总人数:"+Person.totalnum);
	  Person.destroy();
	  System.out.println("人类灭亡后,人类总人数:"+Person.totalnum);
	  
   }
}
-------------------------------------------------
输出结果为:
小猪出生后,人类总人数:1
小牛出生后,人类总人数:2
小牛死亡后,人类总人数:1
人类灭亡后,人类总人数:0

  我用比较白话的方式谈谈自己理解:被static 修饰,就是指这些变量和方法是类本身的东西,与具体的实例化对象无关,我们在调用时应该直接从类中调用:类名.变量/方法。所以调用static方法时,static方法内是不能操作非static变量的,因为非static变量都是属于实例化后的对象的,调用static方法是从类的层面调用,并不具体到某一个对象。

final修饰符

  final:最终的、最后的。
  final修饰符,可以用来修饰方法、变量以及类。

final 变量

  • final变量一旦赋值后,不能被重新赋值。并且被 final 修饰的实例变量必须显式指定初始值。
    final 修饰符通常和 static 修饰符一起使用来创建类常量。
class Person {
	public static final int max_totalnum = 10;
	public static int totalnum;
	private String name;
	private int age;

	Person(String name,int age) {
		this.name = name ;
		this.age = age;
		Person.totalnum++;
	}

}

public class Test {
	
   public static void main(String[] args){
	  // Person.max_totalnum = 20 ;       会报错,无法修改final变量的值
   }
}

final 方法

  • 父类中的 final 方法可以被子类继承,但是不能被子类重写。
    声明 final 方法的主要目的是防止该方法的内容被修改。
class Person {
	public static final int max_totalnum = 10;
	public static int totalnum;
	private String name;
	private int age;

	Person(String name,int age) {
		this.name = name ;
		this.age = age;
		Person.totalnum++;
	}
	
	static final void destroy() {
		Person.totalnum = 0;
	}
}

class Woman extends Person {
	
	Woman(String name, int age) {
		super(name, age);
	}

	// void destroy(){    }  无法重写,会报错
}

final 类

  • final 类不能被继承,没有类能够继承 final 类的任何特性。
final class Person {
	private String name;
	private int age;

	Person(String name,int age) {
		this.name = name ;
		this.age = age;
	}
	
}

class Woman extends Person {     // 会报错,无法继承,因为Person为final类
	
}

abstract 修饰符

  abstract修饰符用于抽象类与接口当中,关于抽象类与接口详细介绍见:《抽象类与接口》

抽象类

  • 被abstract修饰的类为抽象类,抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。

  • 一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。

  • 抽象类可以包含抽象方法和非抽象方法。

abstract class Person {        //抽象类,注意不能同时被 abstract 和 final 修饰
	public static int totalnum;
	private String name;
	private int age;

	Person(String name,int age) {
		this.name = name ;
		this.age = age;
	}
	
	public abstract void die();      //抽象类中可以有抽象方法,有抽象方法一定要声明为抽象类
	
	public static void destroy() {	//抽象类中也可以有非抽象方法
		totalnum = 0;
	}
}

public class Test {
   public static void main(String[] args){
	  new Person();     // 报错,抽象类无法实例化
   }
}

抽象方法

  • 抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。

  • 抽象方法不能被声明成 final 和 static。

  • 任何继承抽象类的非抽象子类必须实现父类的所有抽象方法,除非该子类也是抽象类。

  • 抽象方法的声明以分号结尾,如:public abstract void die(); 不能再加{}

abstract class Person {
	public static int totalnum;
	private String name;
	private int age;

	Person(String name,int age) {
		this.name = name ;
		this.age = age;
	}
	
	public abstract void die();
	
	public static void destroy() {
		totalnum = 0;
	}
}

class Woman extends Person{     //  Woman 为 Person 的 非抽象 子类
 
	Woman(String name, int age) {
		super(name, age);
	}

	@Override                 // 非抽象子类,必须实现抽象父类的所有抽象方法,也是一种重写
	public void die() {
		// TODO Auto-generated method stub
		Person.totalnum--;
	}
	
}

synchronized,volatile与transient

synchronized 修饰符

  • synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。

volatile 修饰符

  • volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

  • 一个 volatile 对象引用可能是 null。

public class MyRunnable implements Runnable
{
    private volatile boolean active;
    public void run()
    {
        active = true;
        while (active) // 第一行
        {
            // 代码
        }
    }
    public void stop()
    {
        active = false; // 第二行
    }
}

  通常情况下,在一个线程调用 run() 方法(在 Runnable 开启的线程),在另一个线程调用 stop() 方法。 如果 第一行 中缓冲区的 active 值被使用,那么在 第二行 的 active 值为 false 时循环不会停止。

  但是以上代码中我们使用了 volatile 修饰 active,所以该循环会停止。

transient 修饰符

  • 序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。

  • 该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。

public transient int limit = 55;   // 不会持久化
public int b; // 持久化
发布了18 篇原创文章 · 获赞 0 · 访问量 414

猜你喜欢

转载自blog.csdn.net/HhmFighting/article/details/104861891
今日推荐