一、static
static 可以用來(lái)修飾變量、方法、代碼塊。
1. static 修飾變量:
被 static 修飾的變量叫靜態(tài)變量或類(lèi)變量, 沒(méi)有被 static 修飾的變量叫實(shí)例變量。
在運(yùn)行時(shí)期, JVM 在加載類(lèi)的時(shí)候?qū)⑼瓿蓪?duì)靜態(tài)變量/類(lèi)變量分配一次內(nèi)存空間, 且在內(nèi)存上只存在一份拷貝, 類(lèi)的所有實(shí)例將共享這份拷貝。
靜態(tài)變量/類(lèi)變量獨(dú)立于該類(lèi)的任何對(duì)象, 它不依賴類(lèi)的特定實(shí)例, 可以通過(guò)類(lèi)名來(lái)訪問(wèn)得到, 也可以通過(guò)實(shí)例名來(lái)訪問(wèn)(不建議)。
而對(duì)于實(shí)例變量, 是每次創(chuàng)建類(lèi)的實(shí)例的時(shí)候都會(huì)為實(shí)例變量分配一次內(nèi)存空間, 實(shí)例變量在內(nèi)存上可能存在多個(gè)拷貝, 但它們之間互不影響。
2. static 修飾方法
被 static 修飾的方法稱為靜態(tài)方法, 與靜態(tài)變量相似的, 它獨(dú)立于該類(lèi)的任何對(duì)象, 它不依賴類(lèi)的特定實(shí)例。
因此靜態(tài)方法中不能使用 this、super 關(guān)鍵字, 也不能調(diào)用非靜態(tài)的變量或方法(因?yàn)榉庆o態(tài)是需依賴于具體的實(shí)例, 如果調(diào)用, 則不能保證其被正確初始化,
而 Java 編譯器是不允許你這么做的)。靜態(tài)方法可以通過(guò)類(lèi)名來(lái)訪問(wèn)得到, 也可以通過(guò)實(shí)例名來(lái)訪問(wèn)(不建議)。
3. static 修飾代碼塊
被 static 修飾的代碼塊叫靜態(tài)代碼塊, JVM 在加載類(lèi)的時(shí)候就會(huì)執(zhí)行這些靜態(tài)代碼塊, 而且只會(huì)被執(zhí)行一次, 因此靜態(tài)代碼塊會(huì)比類(lèi)的構(gòu)造方法優(yōu)先執(zhí)行。
如果一個(gè)類(lèi)中的靜態(tài)代碼塊有多個(gè),JVM 將按照它們?cè)陬?lèi)中出現(xiàn)的先后順序依次執(zhí)行它們。
二、final
final 譯成中文是最終的和不可更改的意思, 它可以用來(lái)修飾非抽象類(lèi), 非抽象成員方法和變量。
1. final 修飾類(lèi)
final 不能用來(lái)修飾 abstract 的類(lèi), 不能被繼承, 它是頂級(jí)類(lèi), 沒(méi)有子類(lèi), 像我們常用的 String 類(lèi)
2. final 修飾變量
final 用來(lái)修飾變量, 那就意味著該變量一旦初始化完成, 那么它的值就不能夠再被改變。
因此, final 修飾的變量必須由程序員手動(dòng)去做初始化給變量賦值, 而且初始化的位置只能是: 定義處、構(gòu)造方法、普通代碼塊(不能是靜態(tài)代碼塊)。
而且這三個(gè)位置中只能選擇一處來(lái)做初始化。
[小延伸: 普通代碼塊實(shí)際上會(huì)被提取到構(gòu)造方法中來(lái)執(zhí)行, 而且會(huì)比構(gòu)造方法體內(nèi)的代碼優(yōu)先執(zhí)行。]
3. final 修飾方法
final 用來(lái)修飾方法表示不允許其子類(lèi)來(lái)覆蓋這個(gè)方法。
final 不能用來(lái)修飾構(gòu)造器(構(gòu)造方法、構(gòu)造函數(shù)、構(gòu)造子), 因?yàn)楦割?lèi)的構(gòu)造器不能夠被繼承, 類(lèi)內(nèi)的 private 方法也不能夠被子類(lèi)繼承,
也就不存在覆蓋之說(shuō)法, 覆蓋僅適用于成員方法, private 修飾的方法實(shí)際上默認(rèn)也是 final 類(lèi)型的。
三、transient
這個(gè)比較陌生, 其實(shí)我壓根就沒(méi)用過(guò).... -_-|| 在 java 源碼里見(jiàn)到過(guò), 不過(guò)沒(méi)有用到的東西向來(lái)學(xué)了就忘的很干脆, 這次是為了找工作, 重新整理一遍。
@Transient 相信很多人都認(rèn)識(shí)這個(gè), 在編一個(gè)實(shí)體類(lèi)寫(xiě) JPA(Java Persistence API, Java 持久化 API)注解的時(shí)候, 會(huì)常常用到這個(gè)注解。
而這里的 transient 和 @Transient 的作用很相似:
Java 的 Serializable 提供了一種持久化對(duì)象實(shí)例的機(jī)制。當(dāng)一個(gè)對(duì)象發(fā)生持久化時(shí), 可能會(huì)有一些特殊的數(shù)據(jù)成員,
是我們不希望用 Serializable 機(jī)制來(lái)保存的。為了在一個(gè)特定對(duì)象的一個(gè)或多個(gè)域上關(guān)閉持久化, 可以在這個(gè)域前加上關(guān)鍵字 transient。
transient 是 Java 的關(guān)鍵字, 用來(lái)表示一個(gè)域不是該對(duì)象串行化的一部分。當(dāng)一個(gè)對(duì)象被串行化的時(shí)候, 被聲明成 transient 的變量的值
不會(huì)包括在串行化里面。
示例:
package test;
import java.io.Serializable;
public class Admin implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private transient String nickname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
package test;
/**
* <!--
* Author : fancy
* Email : fancydeepin@yeah.net
* Date : 2013-02-07
* --!>
*/
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class AdminTest {
public static void main(String[] args) throws Exception{
Admin admin = new Admin();
admin.setName("店小三");
admin.setNickname("小菜一疊");
writeObject(admin);
System.out.println("<------------- 序列化之前 ------------->");
System.out.println("姓名: " + admin.getName());
System.out.println("昵稱: " + admin.getNickname());
admin = (Admin)readObject();
System.out.println("<------------- 反序列化后 ------------->");
System.out.println("姓名: " + admin.getName());
System.out.println("昵稱: " + admin.getNickname());
/**
* 控制臺(tái)執(zhí)行輸出結(jié)果:
*
* <------------- 序列化之前 ------------->
* 姓名: 店小三
* 昵稱: 小菜一疊
* <------------- 反序列化后 ------------->
* 姓名: 店小三
* 昵稱: null
*/
}
//序列化
public static void writeObject(Object obj) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("admin.ser"));
oos.writeObject(obj);
}
//反序列化
public static Object readObject() throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("admin.ser"));
return ois.readObject();
}
}