泛型是在JDK1.5之后引入的,旨在让我们写出更加通用化,更加灵活的代码。通用化的手段在于让数据类型变得参数化,定义泛型时,对应的数据类型是不确定的,泛型方法被调用时,会指定具体类型,其核心目标是为了解决容器类型在编译时安全检查的问题。
泛型:一般用在类、方法、接口中,叫做泛型类、泛型接口、泛型方法
泛型的参数不支持基本类型;泛型相关的信息不会进入到运行时阶段 package demo.generic; public class GenericDemo { public static void main(String[] args) { GenericClassExample<String> strExample = new GenericClassExample<>("abc"); GenericClassExample<Integer> intExample = new GenericClassExample<>(123); System.out.println(strExample.getClass()); // 打印泛型类的类型 System.out.println(intExample.getClass()); // 打印泛型类的类型 } } // **********运行结果********* //class demo.generic.GenericClassExample //class demo.generic.GenericClassExample // 我们可以从运行结果看出strExample和intExample的类型是一样的,因此泛型类的类型约束只在编译时有效
能否在泛型里面使用具备继承关系的类?
使用通配符 ?,但是会使得泛型的类型检查失去意义
给泛型加入上边界 <? extends E>
给泛型加入下边界 <? super E>package demo.generic; public class GenericDemo { //给泛型加如上边界 ? extends E, 泛型类型必须是E的类型或其子类 public static void handleMember(GenericClassExample<? extends Number> integerExample) { Integer result = (Integer) integerExample.getMember() + 100; System.out.println("result is " + result); } //给泛型加入下边界 ? super E ,泛型类型必须是E的类型或其父类 public static void handleSuperMember(GenericClassExample<? super Integer> integerExample) { Integer result = (Integer) integerExample.getMember() + 100; System.out.println("result is " + result); } public static void main(String[] args) { GenericClassExample<String> strExample = new GenericClassExample<>("abc"); GenericClassExample<Integer> integerExample = new GenericClassExample<>(123); GenericClassExample<Number> numberExample = new GenericClassExample<>(new Integer(123)); // handleMember(strExample); // 编译会报错,因为String不是Number的子类 handleMember(integerExample); // 不会报错,因为Integer是Number的子类 handleSuperMember(integerExample); // 不会报错,因为Integer和泛型类的类型相同 handleSuperMember(numberExample ); // 不会报错,因为Number是泛型类Integer的父类 } }
泛型方法: 使用泛型标识符标识的方法// <E> 泛型标识符 public static <E> void printArray(E[] array) { for(E element : array){ System.out.printf("%s",element); } }
泛型字母的含义
E - Element: 在集合中使用,因为集合中存放的是元素
T - Type: Java类
K - Key: 键
V - Value: 值
N - Number: 数值类型
反射 反射的概念及作用反射允许程序在运行时来进行自我检查并且对内部的成员进行操作。反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
反射机制的作用
在运行时判断任意一个对象所属的类
在运行时获取类的对象
在运行时访问java对象的属性、方法、构造方法等
java.lang.reflect类库里面主要的类
Field: 表示类中的成员变量
Method: 表示类中的方法
Constructor: 表示类的构造方法
Array: 该类提供了动态创建数组和访问数组元素的静态方法
反射依赖的Class:用来表示运行时类型信息的对应类
每个类都有唯一一个与之相应的Class对象
Class类为类类型,而Class对象为类类型对象
Class类的特点
Class类也是类的一种,class则是关键字
Class类只有一个私有的构造函数,只有JVM能够创建Class类的实例
JVM中只有唯一一个和类相对应的Class对象来描述其类型信息
获取CLass对象的三种方式
Object -> getClass()
任何数据类型(包括基本数据类型)都有一个“静态”的class属性
通过Class类的静态方法:forName(String className) (常用) package demo.reflect; public class ReflectTarget { public static void main(String[] args) throws ClassNotFoundException { // 第一种方式获取Class对象 ReflectTarget reflectTarget = new ReflectTarget(); Class reflectClass01 = reflectTarget.getClass(); System.out.println("1st: " + reflectClass01); //通过第二种方式获取Class对象 Class reflectClass02 = ReflectTarget.class; System.out.println("2nd: " + reflectClass01); //比较第一种方式获取得class对象和第二种方式获取得class对象是否为同一个 System.out.println(reflectClass01 == reflectClass02); // 第三种方式获取Class对象 Class reflectClass03 = Class.forName("demo.reflect.ReflectTarget"); System.out.println("3rd: " + reflectClass03); //比较第二种方式获取得class对象和第三种方式获取得class对象是否为同一个 System.out.println(reflectClass02 == reflectClass03); } } /************运行结果如下************/ /* * 1st: class demo.reflect.ReflectTarget * 2nd: class demo.reflect.ReflectTarget * true * 3rd: class demo.reflect.ReflectTarget * true * */ /** * 根据运行结果得知:Class对象有且仅有一个 * **/ ```
Class对象就像一面镜子,透过这面镜子可以看到类的结构
反射的主要用法如何获取类的构造方法并使用