一、泛型
1、泛型的本质是为了参数化类型
2、泛型的优点:
-
类型安全:比如往集合list里add不符合参数类型的值时会报错;
-
消除强制转换:在非泛型编程中,将简单类型作为Object传递时会引起Boxing(装箱)和Unboxing(拆箱)操作
3、泛型的使用:
泛型类:泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口(模板模式)
//格式
public class 类名 <泛型类型1,...> {
}
泛型方法:在调用方法的时候指明泛型的具体类型
//格式
public <泛型类型> 返回类型 方法名(泛型类型 变量名) {
}
泛型类接口:类似泛型类
4、泛型通配符:
E: Element (在集合中使用,因为集合中存放的是元素)
T:Type(Java 类)
K: Key(键)
V: Value(值)
N: Number(数值类型)
?: 表示不确定的java类型
-
通配符上界:<? extends T>
在类型参数中使用 extends 表示这个泛型中的参数必须是 E 或者 E 的子类。使用固定上边界的通配符的泛型, 就能够接受指定类及其子类类型的数据。要声明使用该类通配符, 采用<? extends E>的形式, 这里的E就是该泛型的上边界。
-
通配符下界:<? super T>
在类型参数中使用 super 表示这个泛型中的参数必须是 E 或者 E 的父类。
-
无界通配符:<?>,即类型参数可以是任何类型
5、类型擦除:
指在编译期间,所有的泛型信息都会被擦除掉,我们常称为泛型擦除。
@Test
public void test() {
List<String> stringList = new ArrayList<String>();
stringList.add("泛型");
List<Integer> integerList = new ArrayList<Integer>();
integerList.add(1);
System.out.println(stringList.getClass() == integerList.getClass());
}
//结果
true
其中定义了两个List,不过一个是List泛型类型,只能存储字符串。一个是List泛型类型,只能存储整型。最后,我们通过stringList对象和integerList对象的getClass方法获取它们的类的信息,最后发现结果为true。说明泛型类型String和Integer都被擦除掉了,只剩下了原始类型。
二、反射
1、概述:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
反射就是把Java的各种成分映射成相应的Java类,通过Class对象,我们可以去找到各种成分对应的Java类,从而在运行状态中就可以找到目标成分。
- Class类:代表一个类
- Field类:代表类的成员变量(类的属性)
- Method类:代表类的方法
- Constructor类:代表类的构造方法
- Array类:提供了动态创建数组,以及访问数组的元素的静态方法
2、Class类:
Class类的格式如下:
public final class Class<T> extends Object implements Serializable, GenericDeclaration, Type, AnnotatedElement
Class类没有公共构造方法,Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。
3、获取Class对象的三种方式:
-
Object.getClass();
-
任何数据类型(包括基本数据类型)都有一个“静态”的class属性
-
通过Class类的静态方法:forName(String className)(常用)
package fanshe;
/**
* 获取Class对象的三种方式
* 1 Object ——> getClass();
* 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
* 3 通过Class类的静态方法:forName(String className)(常用)
*
*/
public class Fanshe {
public static void main(String[] args) {
//第一种方式获取Class对象
Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
Class stuClass = stu1.getClass();//获取Class对象
System.out.println(stuClass.getName());
//第二种方式获取Class对象
Class stuClass2 = Student.class;
System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
//第三种方式获取Class对象
try {
Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
4、API调用反射
4.1 利用反射实例化对象:
实体类:
public class People {
private String name;
private String age;
public void say(){
System.out.println("my name is "+name+"\t"+age+" years old");
}
}
实例化:
try {
//方式1
People people = (People) Class.forName("com.eryi.People").newInstance();
//方式2
// Constructor<People> constructor=People.class.getConstructor();
// People people= constructor.newInstance();
people.say();
} catch (Exception e) {
e.printStackTrace();
}
所以Java中共有四种方法实例化对象:
-
new
-
clone
-
序列化
-
反射
4.2 获取方法
JAVA提供Method类型来表示方法,Class类中方法相关的API如下:
API | 功能 |
classType.getMethods() | 获取当前类以及父类的public方法 |
classType.getDeclareMethods() | 获取当前类的所有方法 |
classType. getMethod(String name.Class<?>... parameterTypes) | 获得当前类以及父类指定的public方法 |
classType. getDeclaredMethod(String name,Class<?>... parameterTypes) | 获得当前类的指定的Method |
示例:
//获取类对象
Class<?> classType=Class.forName("reflection.emplee");
//调带参构造实例化
Constructor<?> constructor2=classType.getConstructor(new Class[]{String.class,int.class});
emplee e3=(emplee)constructor2.newInstance(new Object[]{"张三",30});
//获得指定方法
Method method1=classType.getDeclaredMethod("toString",new Class[]{});
String result1=(String)method1.invoke(e3, new Object[]{});
System.out.println(result1);
//获得全部方法(包括私有)
Method[] methods=classType.getDeclaredMethods();
for (Method m : methods) {
System.out.println("方法名:"+m.getName()+"\t"+"返回值类型:"+m.getReturnType());
}
//调用私有方法
Method method2=classType.getDeclaredMethod("getName",new Class[]{});
//关闭安全检查
method2.setAccessible(true);
String result2=(String)method2.invoke(e3, new Object[]{});
System.out.println(result2);
4.3 获取属性
JAVA提供Method类型来表示属性,Class类中与属性相关的API如下:
API | 功能 |
classType. getFields() | 获得当前类以及超类的public Field |
classType. getDeclaredFields() | 获得当前类申明的所有Field |
classType. getField(String name) | 获得当前类以及超类指定的public Field |
classType. getDeclaredField(String name) | 获得当前类申明的指定的Field |
field.set(Object obj, Object value) | 通过反射动态设定Field的值 |
Object obj = field.get(Object obj) | 通过反射动态获取Field的值 |
示例:
//获取class对象所指定的属性,包括私有的
Field field = classType.getDeclaredField("name");
//关闭安全检查
field.setAccessible(true);"李四") ;
field.set(employeeSystem.out.println(field.get (employee)) ;