1、java的泛型
泛型是jdk 5 引入的,泛型就是:引用类型作为参数,本质就是参数化类型;
1)、类型擦除:
java的泛型基本上都是在编译器这个层次来实现的,在生成的字节码文件中是不包含泛型类中的信息的,泛型参数在编译的时候被去掉的过程叫做类型擦除。举例:在代码中的定义的List类型,编译成字节码文件之后,jvm看到的就是List,泛型的参数信息是看不到的。
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// 泛型
List<Integer> list = new ArrayList<>();
list.add(1);
System.out.println(list);
Class<? extends List> aClass = list.getClass();
// 查找add方法
Method add = aClass.getDeclaredMethod("add", Object.class);
// 通过反射添加值
Object k1 = add.invoke(list, "k1");
System.out.println("添加之后的值");
System.out.println(list);
}
输出如下所示:
[1]
添加之后的值
[1, k1]
我们在编译的时候添加,肯定是报错的,但是编译之后,就可以通过反射来添加
2)、常用的通配符:
- ?表示不确定的java类型
- T(type)表示具体的一个java类型
- K 和V(key value)表示java中的key和value
- E(element) 代表Element
- <? extends List> 表示: 该通配符代表的类型是List的子类
- <? super T> 表示:该通配符的类型是T类型的父类
3)、泛型的三种方式
1、泛型类
/**
* 泛型例子
*
* @author LZH
* @version 1.0
* @date 2023/05/22 19:24:08
*/
public class Generic<T>{
private T key;
public void Generic(T key){
this.key = key;
}
public T getKey(){
return key;
}
}
实例化泛型类:
Generic<Integer> aa = new Generic<Integer>(23456);
2、泛型接口
public interface Test<T>{
public T method();
}
实现:
不指定类型
public class bb<T> implements Test<T>{
@override
public T method(){
return null;
}
}
指定返回类型:
public class bb<T> implements Test<String>{
@override
public String method(){
return "hello";
}
}
3)、泛型的方法:
public static < E > void printArray( E[] inputArray )
//打印数组的内容
{
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
}
2、深拷贝和浅拷贝
浅拷贝:对基本数据类型进行值传递,对引用类型进行引用类型般的拷贝。(在引用类型时,定义了一个变量指向这个对象)
深拷贝:对基本数据类型进行值传递,对引用类型,创建一个新的对象,赋值其中的内容,叫做深拷贝。(赋值了一个新的对象)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T0AlHiHM-1684762610187)(E:2.png)]
3、java中只有值传递
- 值传递不会改变原来值;
public static void main(String[] args) {
int a = 10;
int b = 20;
changeNum(a,b);
System.out.println("a的值:"+a);
System.out.println("b的值:"+b);
}
static void changeNum(int num1,int num2){
int temp = num1;
num1 = num2;
num2 = temp;
System.out.println("num1的值:"+num1);
System.out.println("num2的值:"+num2);
}
结果:
num1的值:20
num2的值:10
a的值:10
b的值:20
- 引用传递
public static void main(String[] args) {
Person person = new Person();
person.setAge("10");
person.setName("小明");
changePerson(person);
System.out.println(person);
}
static void changePerson(Person person){
person.setName("小红");
person.setAge("16");
System.out.println(person);
}
结果:
Person(name=小红, age=16)
Person(name=小红, age=16)
引用传递:传递的是对象的引用变量,由于每个变量都是指向这个对象的,操作对象的值,会导致其他的变量也会变,这是因为改变了本质。
总结:
- 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)。
- 一个方法可以改变一个对象参数的状态。
- 一个方法不能让对象参数引用一个新的对象。
4、复制的几种方法
1、直接赋值
复制的是引用的变量;
public static void main(String[] args) {
Person person = new Person();
person.setAge("10");
person.setName("小明");
Person person1 = person;
System.out.println(person ==person1);
}
2、clone一个对象
package com.lzh.interviewquestions.entity;
import lombok.Data;
/**
* 实体类
*
* @author LZH
* @version 1.0
* @date 2023/05/22 20:24:17
*/
@Data
public class Person {
private String name;
private String age;
public Person getCloned(Person person) throws CloneNotSupportedException {
return (Person) person.clone();
}
}
public static void main(String[] args) throws CloneNotSupportedException {
// ______________________________
// Person person = new Person();
// person.setAge("10");
// person.setName("小明");
// Person person1 = person;
// System.out.println(person ==person1);
// -----------------------
Person person = new Person();
person.setAge("10");
person.setName("小明");
Person person1 = person.getCloned(person);
System.out.println(person1 == person);
System.out.println("到哪里了");
System.out.println(person1.getName()==person.getName());
// 也是浅拷贝
Person person = new Person();
person.setAge("10");
person.setName("小明");
Person person1 = new Person();
BeanUtils.copyProperties(person,person1);
System.out.println(person.getName() == person1.getName());
}
clone一个对象是两个地址确实不一样,但是里面的属性对应的值是一样的
3、深拷贝一个对象 实现Cloneable接口
public class Person implements Cloneable {
private String name;
private String age;
public Person(String name, String age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return new Person(this.name, this.age);
}
}
// 使用
Person person1 = new Person("小明", "20");
Person person2 = (Person) person1.clone();
序列化(将对象进行序列化,然后再反序列化成新的对象。)
public static <T> T deepClone(T obj) throws IOException, ClassNotFoundException {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return (T) oi.readObject();
}
// 使用
Person person1 = new Person("Tom", "20");
Person person2 = deepClone(person1);