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

相关文章
相关标签/搜索