Java架构师学习笔记---java基础---反射、泛型

Java架构师学习笔记—java基础—反射、泛型

一、反射

1.1 什么是反射

Class是反射的核心。在运行期创建对象实例。

1.2 Class文件

  • 属性
  • 方法(构造方法、静态方法、普通方法)
  • 包路径
  • 类名

1.3 创建Class对象的三种方式

(1)类.class

Class studentClazz = Student.class();

(2)实例.getClass()

Student student = new Student();
Class studentClazz = student.getClass();

(3)Class.forName(“类的全路径”)

Class studentClazz = Class.forName("org.dio.Student");

1.4 通过Class创建对象

(1)不使用反射

Student student = new Student();

(2)使用反射

//获取Class实例
Class studentClazz = Student.class();
//获取构造方法
//无参数构造方法
Constructor<Student> constructor1 = studentClazz.getConstructor();
//有参构造方法
Constructor<Student> constructor2 = studentClazz.getConstructor(String.Class, Integer.Class);
//创建对象
Student student  = constructor2 .newInstance("dio",1);

1.5 使用反射获取属性值

(1)getField()。只能获取public的,包括从父类继承来的字段。

//通过Class对象,获得Field对象,是Student类的属性
Field nameField = studentClazz.getField("name");
//操作Field,获得属性值,获取student实例的对应属性
String name = String.valueOf(nameField.get(student));

(2)getDeclaredField()。可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。其要访问private值需要使用setAccessible(true)。

//通过Class对象,获得Field对象,是Student类的属性
Field ageField = studentClazz.getField("age");
//设置属性可操作
ageField.setAccessible(true);
//操作Field,获得属性值,获取student实例的对应属性
int age= String.valueOf(ageField.get(student));

(3)其他通过Field.java获取类信息的方法

1.6 反射实战

通过反射实现一个工具类,可以让一个对象属性相同的值赋值给另一个对象。

package org.dio.javabasic.reflect;

import org.dio.javabasic.user.Student;

import java.lang.reflect.Field;

public class BeanUtils {

    private static void convert(Object o1, Object o2) throws Throwable {
        //获取class对象
        Class clazz1 = o1.getClass();
        Class clazz2 = o2.getClass();
        //获得fields
        Field[] fields1 = clazz1.getDeclaredFields();
        Field[] fields2 = clazz2.getDeclaredFields();
        //遍历赋值
        for(Field field1 : fields1){
            for (Field field2: fields2) {
                if(field1.getName().equals(field2.getName())){
                    field1.setAccessible(true);
                    field2.setAccessible(true);
                    field2.set(o2, field1.get(o1));
                }
            }
        }
    }

    public static void main(String[] args) throws Throwable {
        Student s1 = new Student(11, "dio", true);
        Student s2 = new Student();
        BeanUtils.convert(s1, s2);
        System.out.println("s1-->s2:"+s1+"--->"+s2);
    }
}

二、泛型

2.1 什么是泛型

字面意思:泛指的类型?在编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型,这种就叫做反省,类似于提供一种模板。泛型使得代码简洁,提高程序健壮性,编码期完成,可读性很高。
泛型的本质是类型参数化允许在定义类、接口、方法时使用类型形参,当使用时指定具体类型。所有使用该泛型的地方都被统一化,保证类型一致。如果未指定具体类型,默认是Object类型。集合体系中的所有类都增加了泛型,泛型也主要用于集合

2.2 泛型的使用

泛型类、泛型接口、泛型方法、派生子类。

2.3 通配符 ?
2.3.1 < ? extends Class> 上限

只能接收Class类型及其子类,只读不写。
List<? extends Student>可以解释为,包含所有从Student继承的类型,实际上就是没有指定具体的类型,编译器无法理解到底是什么Student类型,所以不接收任何类型的Student。

        List<? extends Student> list = new ArrayList<>();
        list.add(new Student());//编译不通过,如下图
        list.add(null);//编译通过,null可以是指所有类型

在这里插入图片描述

2.3.2 < ? super Class> 下限

只能接收Class类型及其父类,只读不写。
List<? super Student>可以解释为,包含Student父类的列表,实际上也没有指定到底是哪个父类,不能保证类型安全,所以就不接收

        List<? super Student> list = new ArrayList<>();
        list.add(new Student());//编译通过
        list.add(new Person());//编译失败,如下图

在这里插入图片描述

2.4 类型擦除 & 桥接方法

因为jvm不能识别泛型,所以我们编写的泛型只存在于编码期,编译的时候会将泛型自动转换为Object,这就是类型擦除。
一个子类在继承(或实现)一个父类(或接口)的泛型方法时,在子类中明确指定了泛型类型,那么在编译时编译器会自动生成桥接方法。
Method.isBridge()方法来判断一个方法是否是桥接方法。

// 最初的代码
public class Node<T> {
  public T data;
  
  public void setData(T data) {
     this.data = data;
  }
}

public class MyNode extends Node<Integer> {
  public void setData(Integer data) {
    ....
  }
}

// jvm不识别泛型,把泛型擦除掉, 兼容老版本jdk
public class Node {
  public Object data;
  
  public void setData(Object data) {
     this.data = data;
  }
}

public class MyNode extends Node {
  
  // 桥接方法,编译器自动生成
  public void setData(Object data) {
     setData((Integer)data)
  }
  
  public void setData(Integer data) {
    ....
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值