2023-05-22 题目

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);

猜你喜欢

转载自blog.csdn.net/weixin_43987718/article/details/130815886