static、final、transient、volatile關鍵字的做用,foreach循環的原理、java原生序列化及Xstream方式序列化

static

英文翻譯靜態的html

1.修飾變量java

2.修飾方法數組

3.靜態代碼塊緩存

4.靜態內部類網絡

5.靜態導包    語法import static   1.import static  ....ClassName.*;2.import static ...ClassName.具體方法;多線程

package com.liuzhihong.test; import org.junit.Test; import static java.lang.Integer.*; import static java.lang.System.out; /** * @ClassName Test2 * @Description * @Author 劉志紅 * @Date 2019/7/17 **/
public class Test2 { @Test public void test() { out.println(compare(1, 3)); } }

final

英文翻譯最終的併發

1.修飾類不被繼承ide

2.修飾方法不能被重寫工具

3.修飾變量   測試

包括成員變量和局部變量(包括行參)。修飾行參的時候只能調用時候賦一次值,後面這個變量就不能被修改了。

具體指引用不可變,內容可變;因此即便是賦相同的值也會報錯,由於引用不能指向其餘對象;對基本類型來講賦值右邊的是常量;引用指向常量後不可變了;對引用數據類型來講,引用指向對象,對象自己能夠改變內容;final修飾數組無心義,由於數組自己不可變。

transient

英文翻譯短暫的

說到這個關鍵字首先就要提到序列化

平時咱們在Java內存中的對象,是沒法進行IO操做或者網絡通訊的,由於在進行IO操做或者網絡通訊的時候,人家根本不知道內存中的對象是個什麼東西,所以必須將對象以某種方式表示出來,即存儲對象中的狀態。一個Java對象的表示有各類各樣的方式,Java自己也提供給了用戶一種表示對象的方式,那就是序列化,其餘方式例如JSON化,XML化,當前也有比較好用的序列化工具,好比Google的protobuf。換句話說,序列化只是表示對象的一種方式而已。OK,有了序列化,那麼必然有反序列化,咱們先看一下序列化、反序列化是什麼意思。

序列化:將一個對象轉換成一串二進制表示的字節數組,經過保存或轉移這些字節數據來達到持久化的目的。

反序列化:將字節數組從新構形成對象。

java 的transient關鍵字的做用是須要實現Serilizable接口,將不須要序列化的屬性前添加關鍵字transient,序列化對象的時候,這個屬性就不會序列化到指定的目的地中。
transient使用小結
1)一旦變量被transient修飾,變量將再也不是對象持久化的一部分,該變量內容在序列化後沒法得到訪問。
2)transient關鍵字只能修飾變量,而不能修飾方法和類。注意,本地變量是不能被transient關鍵字修飾的。變量若是是用戶自定義類變量,則該類須要實現Serializable接口
3)被transient關鍵字修飾的變量再也不能被序列化,一個靜態變量不論是否被transient修飾,均不能被序列化。

例:

//準備序列化的實體類
package
com.liuzhihong.test; import java.io.Serializable; /** * @ClassName Person * @Description 序列化類 * @Author 劉志紅 * @Date 2019/7/17 **/ public class Person implements Serializable { private String name; private transient Integer id; public Person() { } public Person(String name, Integer id) { this.name = name; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", id=" + id + '}'; } }
//進行序列化測試
package com.liuzhihong.test; import org.junit.Test; import java.io.*; /** * @ClassName Test2 * @Description * @Author 劉志紅 * @Date 2019/7/17 **/
public class Test2 { @Test public void test() { Person person=new Person("xiaoqiang",22); //序列化前
 System.out.println(person.toString()); //序列化
        String filePath="D://Person.obj"; ObjectOutputStream os; ObjectInputStream oi; try { os=new ObjectOutputStream(new FileOutputStream(new File(filePath))); os.writeObject(person); //序列化person對象
 oi=new ObjectInputStream(new FileInputStream(new File(filePath))); Person personNew = (Person) oi.readObject();//反序列化
 System.out.println(personNew.toString()); } catch (Exception e) { e.printStackTrace(); }
finally{
os.close();
oi.close();
} } }

測試結果:

Person{name='xiaoqiang', id=22}
Person{name='xiaoqiang', id=null}

volatile 

英文翻譯不穩定的

volatile修飾的變量值發生變化時候,會強制將修改後的值寫入主存中。

非volatile變量不具有這樣的特性,非volatile變量的值會被緩存,線程A更新了這個值,線程B讀取這個變量的值時可能讀到的並非是線程A更新後的值

volatile和synchronized的比較

他們修飾變量,方法,代碼塊的時候  

                          可見性    有序性    原子性    線程阻塞

volatile                 有           有           無            無

synchronized       有           有           有            有

volatile不會讓線程阻塞,響應速度比synchronized高

可見性:當多個線程訪問同一個變量x時,線程1修改了變量x的值,線程一、線程2...線程n可以當即讀取到線程1修改後的值

有序性:即程序執行時按照代碼書寫的前後順序執行。在Java內存模型中,容許編譯器和處理器對指令進行重排序,可是重排序過程不會影響到單線程程序的執行,卻會影響到多線程併發執行的正確性。

原子性:對任意單個volatile變量的讀/寫具備原子性,但相似於volatile++這種複合操做不具備原子性。

例:

package com.liuzhihong.test; /** * @ClassName Test3 * @Description * @Author 劉志紅 * @Date 2019/7/17 **/
public class Test3 { private volatile int num = 0; public void inc() { num++; } public static void main(String[] args) throws InterruptedException { final Test3 t=new Test3(); for (int i = 0; i < 10; i++) { new Thread(() -> { for (int j = 0; j < 1000; j++) { t.inc(); } }).start(); } Thread.sleep(5000); System.out.println(Thread.activeCount()); //保證前面的線程都執行完
        while (Thread.activeCount()>2) Thread.yield(); System.out.println(t.num); } }

運行結果咱們發現 不能保證每次運行的結果都是10000 大多數狀況是小於10000的。

foreach原理

對於集合來講foreach調用的是iterator()方法迭代,由於集合實現了Iterator接口

對於數組來講foreach是調用for循環

Xstream序列化

在transient咱們說到IO或者網絡傳輸的時候對象須要序列化後才能被識別,序列化的方式不少。上面有java原生的序列化。在純java環境中使用,java自帶的序列化反序列化能夠很好的工做由於他是java自帶的,不須要其餘第三方jar包。可是在多語言環境下,用它序列化存儲後很難用其餘語言還原出來。並且序列化後佔據的字節數比較大,序列化和反序列化效率比較低。

這裏用Xstream進行序列化

1.經過XStream中的toXML()進行序列化成字符串str;能夠用一個FileWriter把這個str存入磁盤,也能夠用一個HttpClient傳輸這串str進行網絡通訊。

2.經過XStream中的fromXML()進行反序列化;

代碼以下:

package com.liuzhihong.test; import com.liuzhihong.entity.Person; import com.thoughtworks.xstream.XStream; import org.junit.Test; /** * @ClassName Test * @Description * @Author 劉志紅 * @Date 2019/7/18 **/
public class XStreamTest { //序列化
 @Test public void test1(){ Person person=new Person("xiagou", 2, new int[]{1,2,3,4,5}); XStream xStream=new XStream(); String str = xStream.toXML(person); System.out.println(str); System.out.println("------------------------------------------"); //能夠自定義序列化出來的格式
        Person person1=new Person("小強", 3, new int[]{1,2,3,4}); xStream.alias("Person",Person.class); xStream.aliasField("Name", Person.class, "name"); xStream.aliasField("Id", Person.class, "id"); xStream.aliasField("Count", Person.class, "count"); String str1 = xStream.toXML(person1); System.out.println(str1); } //反序列化
 @Test public void test2(){ String str="<Person>\n" +
             "  <Name>小強</Name>\n" +
             "  <Id>3</Id>\n" +
             "  <Count>\n" +
             "    <int>1</int>\n" +
             "    <int>2</int>\n" +
             "    <int>3</int>\n" +
             "    <int>4</int>\n" +
             "  </Count>\n" +
             "</Person>"; XStream xStream=new XStream(); //帶別名的序列化結果反序列化的時候必須也要把別名對應關係寫全了
        xStream.alias("Person",Person.class); xStream.aliasField("Name", Person.class, "name"); xStream.aliasField("Id", Person.class, "id"); xStream.aliasField("Count", Person.class, "count"); Person person = (Person) xStream.fromXML(str); System.out.println(person); } }

 

XStream支持基本的數據類型,也支持數組集合等;

詳情引用自:https://www.cnblogs.com/xrq730/p/4823684.html

相關文章
相關標籤/搜索