非访问修饰符
非访问修饰符
为了实现一些其他的功能,
static 修饰符,用来修饰类方法和类变量。final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。abstract 修饰符,用来创建抽象类和抽象方法。synchronized 和volatile 修饰符,主要用于线程的编程。
final 修饰符
//-----------------成员变量------------------//
//初始化方式一,在定义变量时直接赋值
private final int i = 3;
//初始化方式二,声明完变量后在构造方法中为其赋值
//如果采用用这种方式,那么每个构造方法中都要有j赋值的语句
private final int j;
public FinalTest() {
j = 3;
}
//如果取消该构造方法的注释,程序就会报错,因此它没有为j赋值
/*public FinalTest1(String str) {
}*/
//为了方便我们可以这样写
public FinalTest(String str) {
this(); //调用无参构造器
}
//下面的代码同样会报错,因为对j重复赋值
/*public FinalTest1(String str1, String str2) {
this();
j = 3;
}*/
//初始化方式三,声明完变量后在构造代码块中为其赋值
//如果采用此方式,就不能在构造方法中再次为其赋值
//构造代码块中的代码会在构造函数之前执行,如果在构造函数中再次赋值,
//就会造成final变量的重复赋值
private final int k;
{
k = 4;
}
//-----------------类变量(静态变量)------------------//
//初始化方式一,在定义类变量时直接赋值
public final static int p = 3;
//初始化方式二,在静态代码块中赋值
//成员变量可以在构造函数中赋值,但是类变量却不可以。
//因此成员变量属于对象独有,每个对象创建时只会调用一次构造函数,
//因此可以保证该成员变量只被初始化一次;
//而类变量是该类的所有对象共有,每个对象创建时都会对该变量赋值
//这样就会造成变量的重复赋值。
public final static int q;
static {
q = 3;
}
final 变量
public class Test{
final int value = 10;
// 下面是声明常量的实例
public static final int BOXWIDTH = 6;
static final String TITLE = "Manager";
public void changeValue(){
value = 12; //将输出一个错误
}
}
final 方法
父类中的
public class Test{
public final void changeName(){
// 方法体
}
}
final 类
public final class Test {
// 类体
}
abstract 修饰符
抽象类
抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。一个类不能同时被
abstract class Caravan{
private double price;
private String model;
private String year;
public abstract void goFast(); //抽象方法
public abstract void changeColor();
}
抽象方法
抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。抽象方法不能被声明成
如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。抽象方法的声明以分号结尾,例如:public abstract sample();。
public abstract class SuperClass{
abstract void m(); //抽象方法
}
class SubClass extends SuperClass{
//实现抽象方法
void m(){
.........
}
}
synchronized 修饰符
public synchronized void showDetails(){
// .......
}
transient 修饰符
序列化的对象包含被
public transient int limit = 55; // 不会持久化
public int b; // 持久化
当对象被序列化时(写入字节序列到目标文件)时,
//定义一个需要序列化的类
class People implements Serializable{
String name; //姓名
transient Integer age; //年龄
public People(String name,int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名 = "+name+" ,年龄 = "+age;
}
}
public class TransientPeople {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
People a = new People("李雷",30);
System.out.println(a); //打印对象的值
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d://people.txt"));
os.writeObject(a);//写入文件(序列化)
os.close();
ObjectInputStream is = new ObjectInputStream(new FileInputStream("d://people.txt"));
a = (People)is.readObject();//将文件数据转换为对象(反序列化)
System.out.println(a); // 年龄 数据未定义
is.close();
}
}
volatile 修饰符
public class MyRunnable implements Runnable
{
private volatile boolean active;
public void run()
{
active = true;
while (active) // 第一行
{
// 代码
}
}
public void stop()
{
active = false; // 第二行
}
}
通常情况下,在一个线程调用
static 修饰符
静态变量并不是说其就不能改变值,不能改变值的量叫常量。其拥有的值是可变的,而且它会保持最新的值。说其静态,是因为它不会随着函数的调用和退出而发生变化。即上次调用函数的时候,如果我们给静态变量赋予某个值的话,下次函数调用时,这个值保持不变。
-
静态变量:
static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝静态变量也被称为类变量。局部变量不能被声明为static 变量。 -
静态方法:
static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。
对类变量和方法的访问可以直接使用
public class InstanceCounter {
private static int numInstances = 0;
protected static int getCount() {
return numInstances;
}
private static void addInstance() {
numInstances++;
}
InstanceCounter() {
InstanceCounter.addInstance();
}
public static void main(String[] arguments) {
System.out.println("Starting with " +
InstanceCounter.getCount() + " instances");
for (int i = 0; i < 500; ++i){
new InstanceCounter();
}
System.out.println("Created " +
InstanceCounter.getCount() + " instances");
}
}
/**
Starting with 0 instances
Created 500 instances
**/
类的静态成员属于整个类 而不是某个对象,可以被类的所有方法访问,子类当然可以父类静态成员;静态方法属于整个类,在对象创建之前就已经分配空间,类的非静态成员要在对象创建后才有内存,所有静态方法只能访问静态成员,不能访问非静态成员;静态成员可以被任一对象修改,修改后的值可以被所有对象共享。
成员变量与类变量的比较
由
成员变量和类变量的区别:
-
两个变量的生命周期不同:成员变量随着对象的创建而存在,随着对象的回收而释放。静态变量随着类的加载而存在,随着类的消失而消失。
-
调用方式不同:成员变量只能被对象调用,静态变量可以被对象调用,还可以被类名调用。
-
别名不同:成员变量也称为实例变量,静态变量也称为类变量。
-
数据存储位置不同:成员变量存储在堆内存的对象中,所以也叫对象的特有数据;静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
类变量的弊端在于,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。静态方法只能访问静态成员,不可以访问非静态成员;因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。静态方法中不能使用
什么时候定义静态成员呢?或者说:定义成员时,到底需不需要被静态修饰呢?
- 成员变量(数据共享时静态化
) ,该成员变量的数据是否是所有对象都一样:如果是,那么该变量需要被静态修饰,因为是共享的数据。如果不是,那么就说这是对象的特有数据,要存储到对象中。
2、成员函数(方法中没有调用特有数据时就定义成静态
static 对 非static 方法调用
public class Xix {
// 静态成员
public static String string="static成员";
// 普通成员
public String string2="非static成员";
// 静态方法
public static void method(){
string="sss";
//string2="sss";编译报错,因为静态方法里面只能调用静态方法或静态成员
//method2();
System.out.println("这是static方法,static方法与对象无关");
}
// 普通方法
public void method2(){
string ="string1";
string2="string2";
method(); //非静态方法里面可以发出对static方法的调用
System.out.println("这是非static方法,此方法必须和指定的对象关联起来才起作用");
}
public static void main(String[] args) {
Xix x=new Xix();
x.method2();// 引用调用普通方法
x.method();// 引用调用静态方法
}
}
/**
这是static方法,static方法与对象无关
这是非static方法,此方法必须和指定的对象关联起来才起作用
这是static方法,static方法与对象无关
**/
因为非