实际开发中,为了对变量进行封装,提高方法和变量访问安全性等,就要用到各种修饰符的功能。
Java修饰符分两种
1、访问修饰符
public 公用的,对所有类可见,可用来修饰类,方法和变量,构造函数
protected 受保护的,同包或子类可见,可用来修饰方法和变量,构造函数
defualt 默认的,不带修饰符,仅对同包可见,可用来修饰类,方法和变量,构造函数
2、非访问修饰符
static
静态修饰符,可以用于修饰类,方法,和变量
修饰类时,作为静态内部类使用。
修饰方法和变量时,程序运行时就加载,不用new 一个对象,就能直接调用,常用final一起用
例子:
/*定义一个静态内部类,里面包含静态方法和静态变量*/ public static final class FinalClass3Static { public static String string = "这是FinalClass3的的静态内部类FinalClass3Static的final3Method()"; public static void final3Method() { System.out.println(string); } }
final
可以用于修饰类,方法,还有变量
当用于修饰类时,该类不能被继承,故没有子类,此final类中的方法默认是final的,反正不能被继承,那也是没办法被重写的了。
当用于修饰方法时,final方法不能被子类重写,但可以被直接调用,也可以被重载
当用于修饰变量时,常与static合用,表示常量,只能被赋值一次,赋值后值不能再被改变。
案例1:
public final abstract class AbstractClass{}
这样写是错的,final不能和abstract共用,因为抽象类的诞生就是为了让子类来继承它 再实现方法的,而加了final之后就无法被继承了,这样定义这类没意义了。
案例2:
public final class AbstractClass{} public class Class2 extends AbstractClass{}
这样写是错的,因为final类无法被继承
案例3:
public class FinalClass{ public final void finalMethod1(){ System.out.println("这是FinalClass下的finalMethod1()方法"); } } public class FinalClass2 extends FinalClass { /*final方法只能在子类直接调用,而无法进行重写*/ @Override public final void finalMethod1() { System.out.println("这是TestFinal2n下的finalMethod1()方法"); } /*随不能重写,但可以重载*/ public static final void finalMethod1(String string){ System.out.println("这是FinalClass2下的finalMethod1()方法"+string); } }
这样写是错的,因为finalMethod1()是final方法,继承的子类只能直接调用该方法,但不能重写final方法。 ps:可以重载该方法
案例4:
public static final String MY_FINAL_STRING ="myFinalString"; MY_FINAL_STRING = “ttt”;
这样写也是错的,无法为final变量重新赋值
abstract
可以用来修饰类和方法,abstract不能和final或static公用。案例中会解释
用于修饰类时,抽象类可以包含抽象方法,也可以不包含抽象方法,但如果是包含抽象方法,则一定要变成抽象类。
当子类继承某抽象类时,必须实现其中的抽象方法。
用于修饰方法时,该方法只能有方法声明,不能包含方法体,需要被子类覆盖重写该方法,才能使用。
不能用来修饰变量。
案例1:
public final abstract void AbstractMethod(){ System.out.println("这是一个抽象方法"); }
这是错的,抽象方法不能再用final来修饰,因为抽象方法只有继承了它的子类才能调用的(而加了final的类不能被继承),也不能有方法体
public static abstract void AbstractMethod(){
System.out.println("这是一个抽象方法"); }
这也是错的,因为static表示静态,而abstract是动态的要运行时才能确定下来
案例2:
public abstract class AbstractClass {}
AbstractClass abstractClass = new AbstractClass();
这是错的,抽象类无法被实例化,不能new,但可以用匿名内部类的方法来实现,如下面
AbstractClass abstractClass = new AbstractClass() { @Override public void AbstractMethod2() { } @Override void AbstractMethod3() { } };
synchronized
当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。 一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
transient
在java中,如果一个对象实现了serializable接口,那么这对象的方法和属性就可以被序列化,但实际开发中,我们有时方法或属性并不想它被序列化,此时就要用到transient关键字,添加了此关键字的属性,在实现serializable接口,不会被序列化 transient关键字只能修饰变量,而不能修饰方法和类
volatile
用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新. 当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的 存在线程安全问题。
Demo工程下载地址
http://download.csdn.net/detail/forgot2015/9732243
参考文章
http://lavasoft.blog.51cto.com/62575/18771/ http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html http://www.cnblogs.com/lanxuezaipiao/p/3369962.html http://www.ibm.com/developerworks/cn/java/j-jtp06197.html