第二十三章、反射
补充动态语言和静态语言区别

1、反射机制

1.1java反射机制示意图


1.2、Java反射机制可以完成
1、在运行时判断任意一个对象所属的类
2、在运行时构造(创建)任意一个类的对象
3、在运行时得到任意一个类所具有的成员变量和方法
4、在运行时调用任意一个对象的成员变量和方法
5、生成动态代理
1.2、java反射的优缺点

1.3、反射相关的主要类

2、Class类
2.1、介绍

2.2、Class类的常用方法

2.3、获取Class的实例
1、内容

2、例子
package reflection;
public class Test03 {
public static void main(String [] args) throws ClassNotFoundException {
Persion persion = new Student();
System.out.println("这个人是:"+persion.name);
// 方式一通过对象获得
Class c1 = persion.getClass();
System.out.println(c1.hashCode());
// 方式二froname获得
Class c2 = Class.forName("reflection.Student");
System.out.println(c2.hashCode());
// 方式三、通过类名.class获得
Class c3 = Student.class;
System.out.println(c3.hashCode());
// 获取父类类型
Class c4 = c1.getSuperclass();
System.out.println(c4);
// 基本内置类型都会有一个
Class [] c5 =c1.getInterfaces();
System.out.println(c5);
}
}
class Persion{
public String name;
public int age;
}
class Student extends Persion {
public Student() {
this.name = "我是个学生";
}
}
class Teacher extends Persion{
public Teacher() {
this.name ="我是个老师";
}
}
2.4、哪些类型可以有Class对象
1、内容

2、例子
Class c1 = Object.class;//类
Class c2 = Comparable.class;//接口
Class c3 = String [].class;//一维数组
Class c4 = int[][].class;//二维数组
Class c5 = Override.class;//注解
Class c6 = ElementType.class;//枚举
Class c7 = Integer.class;//基本数据类型
Class c8 = void.class;//方法
Class c9 = Class.class;//类
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
//只要元素类型与维度一样,就是同一个class
int [] a = new int [10];
int [] b = new int [10000];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
结果
/**
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
366712642
366712642 *//
2.5、java中内存分析
1、图解

2、类加载的过程

3、类的加载与ClassLoaderd的理解

4、什么时候会发生类的初始化

2.6、类加载器
1、作用

2、类加载器的个数

2.7、获取运行时类的完整形式
package reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
// 获取类的名字
Class c1 = Class.forName("reflection.User");
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
// 获取类的属性
Field[] fields = c1.getFields();//只能找到公共的类public
fields = c1.getDeclaredFields();//找到全部的属性
for (Field field:fields) {
System.out.println(field);
}
// 获取指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
// 获取类的方法
System.out.println("================");
Method [] methods = c1.getMethods();//获取所有类的方法
for (Method method : methods) {
System.out.println("正常的:"+method);
}
methods = c1.getDeclaredMethods();//获得本类的所有方法
for (Method method : methods) {
System.out.println("DeclaredMethods:"+method);
}
// 获取指定属性的值
Field name1 = c1.getDeclaredField("name");
System.out.println(name);
// 获取类的指定方法
System.out.println("================");
Method getName = c1.getMethod("getName",null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
// 获取全部构造器
System.out.println("================");
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println("区分"+constructor);
}
// 获取指定的构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
System.out.println("指定:"+declaredConstructor);
}
}
/**
结果
"C:\Program Files\Java\jdk1.8.0_351\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2\lib\idea_rt.jar=1904:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_351\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_351\jre\lib\rt.jar;C:\Users\qt\IdeaProjects\chapter21\out\production\chapter21" reflection.Test08
reflection.User
User
private java.lang.String reflection.User.name
private int reflection.User.id
private int reflection.User.age
private java.lang.String reflection.User.name
================
正常的:public java.lang.String reflection.User.getName()
正常的:public int reflection.User.getId()
正常的:public void reflection.User.setName(java.lang.String)
正常的:public void reflection.User.setId(int)
正常的:public void reflection.User.setAge(int)
正常的:public int reflection.User.getAge()
正常的:public final void java.lang.Object.wait() throws java.lang.InterruptedException
正常的:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
正常的:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
正常的:public boolean java.lang.Object.equals(java.lang.Object)
正常的:public java.lang.String java.lang.Object.toString()
正常的:public native int java.lang.Object.hashCode()
正常的:public final native java.lang.Class java.lang.Object.getClass()
正常的:public final native void java.lang.Object.notify()
正常的:public final native void java.lang.Object.notifyAll()
DeclaredMethods:public java.lang.String reflection.User.getName()
DeclaredMethods:public int reflection.User.getId()
DeclaredMethods:public void reflection.User.setName(java.lang.String)
DeclaredMethods:public void reflection.User.setId(int)
DeclaredMethods:public void reflection.User.setAge(int)
DeclaredMethods:public int reflection.User.getAge()
private java.lang.String reflection.User.name
================
public java.lang.String reflection.User.getName()
public void reflection.User.setName(java.lang.String)
================
public reflection.User(java.lang.String,int,int)
区分public reflection.User(java.lang.String,int,int)
指定:public reflection.User(java.lang.String,int,int)
Process finished with exit code 0
*//
3、class应用
3.1、有了class有啥用
1、作用

3.2、调用指定的方法


3.3、setAccessible:安全访问机制

3.4、反射实例(基础操作)
package reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test09 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
// 通过构造器创建对象
Class c1 = Class.forName("reflection.User");
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
User user2 = (User) constructor.newInstance("秦涛",001,18 );
System.out.println(user2);
// 通过反射调用普通方法
User user3 = (User) c1.newInstance();
// 通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName",String.class);
// invoke:是调用、激活的意思
setName.invoke(user3,"秦涛");
System.out.println(user3.getName());
System.out.println("99999999999999999999999999999999999999999999999999999999");
// 通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
name.setAccessible(true);
name.set(user4,"秦涛111111");
System.out.println(user4.getName());
//
}
}
3.5、反射性能对比
1、排行
1、普通方法>反射调用(关闭安全检测)>反射调用
2、例子
package reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test10 {
// 普通调用测试时间
public static void test01(){
User user = new User();
long startTime = System.currentTimeMillis();
for(int i =0;i<1000000000;i++){
user.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方法调用跑了:"+(endTime-startTime)+"ms");
}
// 反射进行方法调用测试时间
public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName",null);
long startTime = System.currentTimeMillis();
for(int i =0;i<1000000000;i++){
getName.invoke(user,null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方法调用对象跑了:"+(endTime-startTime)+"ms");
}
//反射关闭安全检测进行测试时间
public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName",null);
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for(int i =0;i<1000000000;i++){
getName.invoke(user,null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射关闭安全检测调用对象跑了:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
test01();
test02();
test03();
}
}
3.6、反射操作泛型
1、作用、介绍

2、例子
package reflection;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class Test11 {
public void test01(Map<String, User> map , List<User> list){
System.out.println("test01");
}
public Map<String,User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = Test11.class.getMethod("test01", Map.class,List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("**:"+genericParameterType);
if(genericParameterType instanceof ParameterizedType){ //进行判断genericParameterType是否为一个参数化类型
Type[] autualTypeArguments = ((ParameterizedType)genericParameterType).getActualTypeArguments();//如果是,进行强转,调用getActualTypeArguments()方法获得真是获得真是的参数类型
for (Type autualTypeArgument : autualTypeArguments) {
System.out.println(autualTypeArgument);
}
}
}
method = Test11.class.getMethod("test02",null);
Type[] genericParameterType1 = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterType1) {
System.out.println("**:"+genericParameterType);
if(genericParameterType instanceof ParameterizedType){ //进行判断genericParameterType是否为一个参数化类型
Type[] autualTypeArguments = ((ParameterizedType)genericParameterType).getActualTypeArguments();//如果是,进行强转,调用getActualTypeArguments()方法获得真是获得真是的参数类型
for (Type autualTypeArgument : autualTypeArguments) {
System.out.println(autualTypeArgument);
}
}
}
}
}
/**
结果
**:java.util.Map<java.lang.String, reflection.User>
class java.lang.String
class reflection.User
**:java.util.List<reflection.User>
class reflection.User
Process finished with exit code 0
3.7、练习ORM
1、内容

2、例子
package reflection;
import com.sun.istack.internal.Interned;
import java.lang.annotation.*;
import java.lang.reflect.Field;
/**
*
* 反射操作注解
*/
public class Test12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("reflection.Student2");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 获取注解的value的值
Tabletao tabletao = (Tabletao) c1.getAnnotation(Tabletao.class);
String value = tabletao.value();
System.out.println(value);
// 获取类指定的注解
Field f = c1.getDeclaredField("age");
Filetao annotation = f.getAnnotation(Filetao.class);
System.out.println(annotation.colunName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@Tabletao("db_student")
class Student2{
@Filetao(colunName = "db_id",type = "int",length =10)
private int id;
@Filetao(colunName = "db_age",type = "int",length =8)
private int age;
@Filetao(colunName = "db_name",type = "int",length =5)
private String name;
public Student2() {
}
public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student2{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//类名的注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Tabletao{
String value();
}
//属性的注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface Filetao{
String colunName();
String type();
int length();
}