传智播客培训2.19 泛型和反射

简介:

一、泛型

 

1.       为什么使用泛型?

       jdk5以前,对象一旦存入集合就是去特性,变成Object类型

       从集合取出元素时,就需要做强转,

       有的时候我们不确定集合中到底存储的是什么类型,强转时容易出错

 

       jdk5中,为了提供集合的安全性,定义了泛型,我们可以在使用集合时利用泛型

       限定集合存入的数据类型

 

2.       用泛型的好处?

        在迭代集合时,可以避免强转的麻烦

        将运行时期的错误转移到编译阶段

3.       由于集合是用于存储对象的,基本数据类型需要包装后才能存入集合,所以

       集合上使用的泛型必须是引用数据类型

 

4.       什么情况下用泛型

       如果一个类有两个或多个方法的形参必须为同一种类型,或者方法的返回值必须为同一种类型

       就可以使用泛型来解决

 

       简单来说,在一个类中多个方法使用的类型必须是同一种类型,但是可以为任意类型

5.       List<T> 当中T称为类型参数  List<String> 当中String 实际类型参数

6.       自定义泛型

       在类的后面自定义泛型,类型多处用到的类型需要是同一种类型

// 一个学生对象学习什么就必须玩什么

public class Student<T,E> {

 

    // 使用类型参数

    public T study(T t) {

       return null;

    }

   

    public void play(T t) {

      

    }

 

    public void eat(E e) {

      

    }

}

 

    定义泛型方法, 方法的形参和返回值需要是同一种类型

// 求两个数的最大数

// 判断两个对象中的较大者

public static <T> T getMax(T x, T y) {

    /*if(x>y)

       return x;

    return y;*/

    // TreeSet

    // 判断x对象是否具备比较的功能

    if(x instanceof Comparable) {

       Comparable com = (Comparable) x;

       int num = com.compareTo(y);

       if(num>0)

           return x;

       return y;

    }

    // 说明x不具备比较功能

    throw new RuntimeException("对不起,比不了!");

   

 

   

}

 

public static <T> void reverse(T[] arr) {

    int start = 0;

    int end = arr.length - 1;

    while(end>start) {

       T temp = arr[start];

       arr[start] = arr[end];

       arr[end] = temp;

       start++;

       end--;

    }

}

 

二、反射

 

1.       理解Class

   对象都是根据类创建出来的—>创建一个对象代表李四这个人—>李四(跑起来)

       Person.class(描述所有和李四类似的事物的信息) à Person对象 à 李四(赵六、王五)

       Class.class(描述字节码这类事物的特征) –> Class对象—> Person.class字节码(Student.class Boy.class String.class)

 

所有的Person对象能做的事情都用方法来描述,例如跑步用run方法描述

所有的Class对象(字节码)能做的事情用方法来描述,例如创建对象用newInstance来描述

 

2.       通过反射获得Class对象

三种方式获得

// 1. 根据给定的类名来获得

String methodname = "run";

String classname = "cn.itcast.reflect.Person";   // 来自配置文件

Class clazz = Class.forName(classname);   // 此对象代表Person.class

Object obj = clazz.newInstance();  // 创建对象

 

 

// 2. 如果拿到了对象,不知道是什么类型

Object obj = new Person();

Class clazz1 = obj.getClass();  // 获得对象具体的类型

 

// 3. 如果是明确地获得某个类的Class对象

Class clazz2 = Person.class;    // 主要用于传参

 

// java中所有的类型都会对应一个Class对象 int Integer

Class intClazz = int.class;

Class intarrClazz = int[].class;

Class voidClazz = void.class;

 

3.       反射能做什么事情

// 调用任何一个对象的任何方法

// 读取配置文件获得如下信息

String classname = "cn.itcast.reflect.Student";

String methodname = "study";

 

 

// Personrun方法调用

// 1.创建Person对象

Class clazz = Class.forName(classname);   // 此对象代表Person.class

Object obj = clazz.newInstance();  // 创建对象

// 2.获得表示run方法的对象

Method runMethod = clazz.getMethod(methodname);

// 3.通过Person对象来调用run方法

 

4.       通过反射获得类的成员变量

// 获得代表某个属性的Field对象

Class clazz = Person.class;

 

Field[] fields = clazz.getDeclaredFields();

for(Field field : fields) {

    String name = field.getName();  // 获得属性名

    Class type = field.getType();   // 获得属性的类型

    System.out.println("属性名:" + name + "属性类型:" + type);

}

 

// 获得对象的某个指定的属性,并为该属性赋值

// 明确告诉你,获得name属性

String fieldname = "name";

Object obj = new Person();

 

// 1. 获得Class对象()

Class clazz1 = obj.getClass();

// 2. 获得指定的属性

Field nameField = clazz1.getDeclaredField(fieldname);

// 3. 为属性赋值

// 私有属性不行,因为java虚拟机会检查访问权限

// 如果一定要访问,就需要取消java访问检查

nameField.setAccessible(true);

nameField.set(obj, "zhangsan");

/*

Person p = (Person) obj;

System.out.println(p.getName());*/

Object value = nameField.get(obj); // 获得指定对象上该字段的值

System.out.println(value);

5.       通过反射获得类的构造方法

// 获得类

Class clazz = Person.class;

 

// 获得类的所有构造函数

Constructor[] constructors = clazz.getConstructors();

for(Constructor con : constructors) {

    // 遍历参数类型

    Class[] parameterTypes = con.getParameterTypes();

    for(Class type : parameterTypes)

       System.out.print(type.getName() + "   ");

    System.out.println();

}

 

// 获得指定的构造函数,创建对象

// 要求调用参数为 String int 的构造函数

// 1. 反射出指定的构造函数

Constructor con = clazz.getConstructor(String.class, int.class);

// 2. 调用构造函数创建对象

Object obj = con.newInstance("wangwu", 23);

System.out.println(obj); // toString

6.       通过反射获得类的成员方法

Class clazz = Person.class;

 

// 获得类的所有方法

Method[] methods = clazz.getDeclaredMethods();

for(Method m : methods) {

    String name = m.getName();  // 方法名

    System.out.print("方法名:" + name);

    // 参数类型

    System.out.print(", 参数类型依次为:");

    Class[] types = m.getParameterTypes();

    for(Class type : types)

       System.out.print(type.getName() + "  ");

    // 返回值类型

    Class returnType = m.getReturnType();

    System.out.print(",返回值类型:" + returnType.getName());

    System.out.println();

}

 

// 反射出指定的方法,调用

// 创建一个对象

Object obj = clazz.newInstance();

// 调用play方法

Method playMethod = clazz.getMethod("play", String.class);

playMethod.invoke(obj, "zhangsan");

// 调用eat方法

Method eatMethod = clazz.getMethod("eat");

eatMethod.invoke(null);

// 调用sleep方法

Method sleepMethod = clazz.getMethod("sleep", String[].class);

String[] arr = {"a","b"};

sleepMethod.invoke(obj, (Object)arr);  // 符合1.41.5的语法

相关文章
|
7月前
|
Java 编译器
Java反射操作泛型
Java反射操作泛型
38 0
|
2天前
|
Java 编译器
每日一道Java面试题:方法重载与方法重写,这把指定让你明明白白!
每日一道Java面试题:方法重载与方法重写,这把指定让你明明白白!
14 0
|
7月前
|
XML 安全 Java
【javaSE】 反射与反射的使用
【javaSE】 反射与反射的使用
|
4月前
|
Java
反射获取声明泛型工具类
反射获取声明泛型工具类
27 0
|
9月前
|
编译器
反射、注解和泛型相关的坑
泛型 类型擦除 桥接方法
|
9月前
|
编译器
反射、注解和泛型相关的坑
根据反射来获取方法,很多人觉得获取方法传入参数就可以了,但是遇到方法的重载的时候,怎么能够知道此次执行走的是哪个方法呢?
|
11月前
|
Java 程序员
彻底弄懂Java的泛型1 - 泛型类
彻底弄懂Java的泛型1 - 泛型类
179 0
|
Java
获取java泛型类中的泛型类型
实现java中获取泛型类中的泛型类型的方法
230 0
|
Java API Android开发
Java反射实践:从反射中理解class
写在前面 今天在需求评审的时候,遇到了挺有意思的要求。需求是什么样子就不说了。总之完成这个需求需要一个调用系统api的操作。然而这个api因为并不稳定的原因。
1074 0