java基础(三).ConcurrentHashMap原理,深拷贝和浅拷贝,序列化与反序列化,反射

java基础(三)ConcurrentHashMap原理,深拷贝和浅拷贝,序列化与反序列化,反射

          • 1.ConcurrentHashMap原理
          • 2.new String("")创建几个对象?
          • 3.Java序列化与反序列化原理
          • 4.深拷贝和浅拷贝的区别
          • 5.反射

1.ConcurrentHashMap原理

HashMap缺点:
     线程不安全,多线程情况下,同时进行resize操作可能引起死循环,还有,两个线程同时进行 put操作时,也可能导致put失败。
HashMap的key和value都允许放入null值。

HashTable缺点:
     HashTable采用sychronized来保证线程安全,但是在线程激烈竞争情况下,效率非常低。一个线程访问HashTable的同步方法时,其他线程接着访问的话,可能会进入阻塞或者轮询状态。比如线程1使用put方法添加元素,那么线程2既不能使用put添加元素,也不能使用get获取元素,导致效率降低。
HashTable不允许null值。

ConcurrentHashMap
      ConcurrentHashMap采用 “分段锁”,在容器中有多把锁,每个锁锁住一段数据,这样在多线程访问不同段的数据时,就不会存在锁竞争了,提高并发效率。
原理:

ConcurrentHashMap维护一个Segment数组,一个Segment维护一个HashEntry数组。
对于ConcurrentHashMap的数据插入,这里需要进行两次Hash计算去定位数据的存储位置。
Segment实现了ReenTrantLock,也就带有锁的功能,当执行put操作时,会进行第一次key的hash操作,来定位到segment的位置,如果该segment还没有初始化则直接放入,
否则进行第二次hash值的计算,找到对应的HashEntry位置。在将数据插入到HashEntry链表时(链表的尾端),会通过继承的ReenTrantLock的tryLock()方法去尝试获取锁,
如果获取成功就直接插入到该位置,如果已经有线程获取该位置的锁了,那当前线程就会以自旋的方式去继续的调用tryLock()方法去获取锁,超过指定次数就挂起,等待被唤醒。

2.new String("")创建几个对象?

      1个或者2个,java中有String常量池,每当创建一个新对象时,就先去常量池中找是否有这个字符串,有的话就不在常量池中创建新对象,没有的话就创建一个对象,另外一个对象是在堆上创建。

3.Java序列化与反序列化原理

      3.1 Java序列化是指将java对象转化为字节序列的过程,而java反序列化是把字节序列恢复为对象的过程。
序列化的作用:

在传递和保存对象的时候,保证对象的完整性。序列化是把对象转化为有序字节流,以便在网络上传输或者保存在本地文件中。

反序列化
客户端从文件或者网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态以及描述信息,通过反序列化重建对象。

3.2 序列化与反序列化的作用以及好处:
适用于当两个java进程进行通信时

  • (1)实现了数据的持久化,通过序列化可以把数据持久的放在硬盘上(通常存放在文件里)
  • (2)利用序列化进行远程通信,即通过网络传输传送对象。

3.3 与序列化相关的API:
(1)ObjectOutputStream:表示对象输出流
它的writeObject可以对指定参数的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
(2)ObjectInputStream:表示对象输入流
它的readObject方法可以源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回。

4.深拷贝和浅拷贝的区别

      浅拷贝 是指在拷贝对象时,对于基本数据类型的变量会重新复制一份,因此是两份不同的数据,修改其中一份,另一份不会被影响。
而对于引用类型的变量只是对引用进行拷贝,这两个引用都指向同一个地址,因此修改其中一个另一个也会改变。
      深拷贝 则是对对象以及该对象关联的内容,都进行拷贝,修改其中一个,另一个不会改变。
举例:假如B复制了A,当修改了A之后,看B是否变化,如果B变化了,则说明是浅拷贝,如果B没变,则说明是深拷贝。

深拷贝可以采用的方法:
1.采用 JSON.stringify 和 JSON.parse

function deepClone(obj){
    let _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
    return objClone
}  

2.对对象进行深拷贝
(1)每一个对象都实现Cloneable接口,并重写clone()方法,最后在最顶层的类重写的clone()方法中调用所有的clone()方法即可实现深拷贝。

(2)通过序列化实现深拷贝,每个对象都要实现Serializable接口。

		Age a=new Age(20);
        Student stu1=new Student("张三",a,175);
        //通过序列化方法实现深拷贝
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(stu1);
        oos.flush();
        
        ObjectInputStream ois=new ObjectInputStream(new	ByteArrayInputStream(bos.toByteArray()));
        Student stu2=(Student)ois.readObject();  
5.反射

5.1 反射的原理:
Java语言编译后会形成一个.Class文件,反射就是通过字节码文件找到某一个类,类中的方法以及属性等。

5.2 反射的实现主要借助四个类:

Class:类的对象
Constructor:类的构造方法
Field:类中的属性对象
Method:类中的方法对象

5.3 使用反射机制的步骤:
1.导入java.lang.reflect包
2.遵循三个步骤:

  • 获取你想操作的类对象
  • 调用相关反射的方法(比如getDeclaredMethods)
  • 使用反射API来操作

5.4 获取Class对象的方法:
(1)根据对象来获取

  Class c = 对象名.getClass();

(2)直接写类路径全称

Class c = java.awt.Button.class;

(3)包装类:Class c = Integer.TYPE;

(4)Class.forName

  // 要求JVM查找并加载指定的类,这时候,
  // 会把静态属性,方法以及静态代码块都加载到内存中
  Class t = Class.forName("com.TestOne");
  // 产生这个Class对象的一个实例,调用该类的无参构造方法,作用等同于new TestOne();
   t.newInstance();

5.5 Class对象可以调用的方法:

方法名 介绍
getName() 获得类的完整名字。
getFields() 获得类的public类型的属性。
getDeclaredFields() 获得类的所有属性。包括private 声明的和继承类
getMethods() 获得类的public类型的方法。
getDeclaredMethods() 获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[] parameterTypes) 获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors() 获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes) 获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance() 通过类的不带参数的构造方法创建这个类的一个对象。

5.6 Class能实现的功能:
1.判断对象属于哪个类
2.获取类信息
3.构建对象
4.动态执行方法,通过invoke调用

   Class class1 = Person.class;
	Method work = class1.getDeclaredMethod("work");
	Person person = new Person();
	work.invoke(person);

5.动态操作属性

	Class class1 = Person.class;
    Person person = new Person();
    Field field = class1.getDeclaredField("age");
	//age默认值是18
    field.set(person,22);
    System.out.println(person.age);

6.动态代理

5.7 newInstance 和 new的区别:
前者是使用类加载机制,后者是创建一个新类。
newInstance的使用更加局限,只能调用无参构造,但是使用new可以调用任何public构造。
从JVM角度看,使用new关键字的时候,这个类可以没有被加载,但是使用newInstance的时候,就必须保证这个类已经加载了,这个类已经连接了。

你可能感兴趣的:(面试)