反射Reflection
静态语言(c、c++)和动态语言(JavaScript) 动态语言:程序运行的时候可以改变其结构,成为动态语言。 eg:
function jsMethod(){
var x="3;var y=5;alert(x+y)"
执行该方法,会将原本为字符串的x变为一段代码的执行,这种语言即为动态语言
}
Java通过反射可以达到动态语言的效果;
一个类在内存中只有一个Class对象 一个类被加载后,类的整个结构都会被封装在Class对象中。
反射得到的是一个Class类,此类是Java反射的源头,即通俗的理解为:通过对象反射出类的名称
获取Class对象的几种方式
Class类的特性: 一个类型的类在JVM中只会有一个Class实例 
package yh.com.pojo
class Person{
private String name;
Person(){
this.name="人类";}
}
class Teacher extends Person{
Teacher(){
this.name="老师";}
}
public class TestClass{
public stastic void main(String args[]){
Student s=new Teacher();
Class c1=s.getClass();
System.out.println(c1.hashCode());
Class c2=Class.forName("yh.com.pojo.Teacher")
System.out.println(c2.hashCode());
Class c3=Teacher.class;
System.out.println(c3.hashCode());
Class c4=Integer.Type;
System.out.println(c4);
System.out.println(c4.hashCode());
Class c5=c1.getSupercclass();
System.out.println(c5);
System.out.println(c5.hashCode());
}
}
Class类的常用方法:
- static ClassforName(String name):返回指定类名的class对象
- Object newIntence():调用无参构造器返回一个class对象的实例
- getName():返回该class对象所表示的实体(类、接口、数组、void等)的名称
- getSuperClass():获取当前class对象的父类的class对象
可以有Class对象的类型
 eg:  比如数组和二维数组是不同维度的
存内存分析反射流程
帮助理解反射,了解即可
- 加载class文件到内存的方法区,会在堆中产生一个包含类中所有信息的Class对象
- 链接:验证class文件信息,以及初始化静态变量。如是static m=0;
- 初始化:
执行< clinit >(){}方法,对类中的静态代码和静态常量进行合并到方法体中进行执行
Class A{
static{
sout("A类的静态代码块初始化")
m=300;
}
static int m=100
public A(){
sout("A类的无参构造初始化")
}

类加载器
- 引导类加载器:用来加载核心类库。该加载器无法直接获取。
- 扩展类加载器:负责加载jre/lib/ext目录下的jar包或者-D java.ext.dirs指定目录下的jar包的加载
- 系统类加载器(常用):负责加载java仙姑classpath下的jar包。
双亲委派模型:多重检测,检测自己写的类在系统加载路径中是否已存在,如果存在则会使用根加载器下的类而不会使用自定义的
使用反射获取
获取Class对象、获取类名、获取变量名、获取方法名、获取构造器
package Test;
class Person {
String name;
public long idCard;
Person() {
this.name = "人类";
}
public String method(String name) {
System.out.println("带返回类型和参数的方法" + name);
return name;
}
}
class Teacher extends Person {
private int id;
private String home;
public String address;
Teacher() {
this.name = "老师";
}
Teacher(int id, String home) {
this.id = 1;
this.name = "老师带参数";
}
public void method1() {
System.out.println("public修饰的无参方法");
}
void method2() {
System.out.println("无参方法");
}
public String method3(String name) {
System.out.println("带返回类型和参数的方法" + name);
return name;
}
}
获取类的变量
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class aClass = Class.forName("test.Teacher");
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("---------------------");
fields = aClass.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("=====================");
Field address= aClass.getField("address");
Field idCard = aClass.getField("idCard");
System.out.println(address);
System.out.println(idCard);
System.out.println("---------------------");
Field id = aClass.getDeclaredField("id");
System.out.println(id);
System.out.println("=====================");
}
}
获取类的方法:
public class ReflectTest {
public static void main(String[] args) throws Exception, NoSuchFieldException {
Class aClass = Class.forName("test.Teacher");
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("-----------------");
methods=aClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("================");
Method method1 = aClass.getMethod("method1", null);
System.out.println(method1);
Method method = aClass.getMethod("method", String.class);
System.out.println(method);
System.out.println("-----------------");
Method method2 = aClass.getDeclaredMethod("method2", null);
System.out.println(method2);
Method method3 = aClass.getDeclaredMethod("method3", String.class);
System.out.println(method3);
}
}
获取类的构造器:
public class ReflectTest {
public static void main(String[] args) throws Exception, NoSuchFieldException {
Class aClass = Class.forName("test.Teacher");
Constructor[] constructors = aClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("-------------------");
Constructor[] cs = aClass.getDeclaredConstructors();
for (Constructor c : cs) {
System.out.println(c);
}
System.out.println("================");
Constructor c = aClass.getConstructor();
System.out.println(c);
System.out.println("-----------------");
Constructor cons = aClass.getDeclaredConstructor(int.class);
System.out.println(cons);
Constructor cons1 = aClass.getDeclaredConstructor(int.class,String.class);
System.out.println(cons1);
}
}
使用反射 *
-
创建对象的实例 创建无参构造时可以通过class对象的newInstance()方法直接创建。 根据有参构造创建时可以通过获取有参构造器然后使用构造器的newInstance(参数值)方法进行创建 -
执行对象对象的方法 通过class对象的getMethod(参数一:方法名,参数二:方法参数的类型)方法获取到相应方法,执行invoke(参数一:所属对象,参数二:方法所需要的参数的值)激活方法来执行获取到的方法 -
直接给属性赋值 先获取field对象然后执行set(参数一:要操作的对象,参数二:要设置的值)方法 -
setAccessible():可以提高反射效率 当方法、构造器或者属性对象在对应类中的修饰符为private时,在使用这些对象执行某些操作之前设置暴力反射即可正常获取和执行 当权限不足时可以设置暴力反射,即关闭了代码的安全检测 属性or方法名.setAccessible(true); 如给私有属性赋值时失败
如执行类的private类型的方法时在invoke之前设置即可 如在使用类的private构造器创建对象时,在此之前设置即可
Class aClass = Class.forName("test.Teacher");
Teacher teacher = (Teacher) aClass.newInstance();
System.out.println(teacher);
Constructor c = aClass.getDeclaredConstructor(int.class, String.class);
System.out.println(c);
Object o = c.newInstance( 2, "有参");
System.out.println(o);
System.out.println("=================");
Method methot1 = aClass.getDeclaredMethod("method1");
System.out.println(teacher);
methot1.invoke(teacher);
methot1=aClass.getDeclaredMethod("method3", String.class);
methot1.invoke(teacher,"为方法的home属性传递的参数");
System.out.println(teacher);
System.out.println("=================");
Constructor c1 = aClass.getDeclaredConstructor(int.class);
c1.setAccessible(true);
Teacher o1 = (Teacher) c1.newInstance(5);
System.out.println(o1);
Method method2 = aClass.getDeclaredMethod("method2");
method2.setAccessible(true);
method2.invoke(teacher);
Field name = aClass.getDeclaredField("home");
name.setAccessible(true);
name.set(teacher,"反射给name设置值");
System.out.println(teacher);
setAccessible提升效率测试
public class ReflectTest {
public static long start;
public static long end;
public static void test1() {
Teacher teacher = new Teacher();
start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
teacher.method1();
}
end = System.currentTimeMillis();
System.out.println("new :" + (end - start));
}
public static void test2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class<?> aClass = Class.forName("test.Teacher");
Teacher o = (Teacher) aClass.newInstance();
Method method1 = aClass.getDeclaredMethod("method1");
start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
method1.invoke(o);
}
end = System.currentTimeMillis();
System.out.println("Class :" + (end - start));
}
public static void test3() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class<?> aClass = Class.forName("test.Teacher");
Teacher o = (Teacher) aClass.newInstance();
Method method1 = aClass.getDeclaredMethod("method1");
method1.setAccessible(true);
start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
method1.invoke(o);
}
end = System.currentTimeMillis();
System.out.println("Class+Accessible :" + (end - start));
}
public static void main(String[] args) throws Exception, NoSuchFieldException {
test1();
test2();
test3();
System.out.println("毫秒");
}
}
反射获取泛型信息
了解即可 

https://www.bilibili.com/video/BV1p4411P7V3?p=15&spm_id_from=pageDriver
反射获取注解信息
此处用于帮助理解框架的底层原理
package test;
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class AnnoationRTest {
public static void main(String[] args) throws Exception {
Class aClass = Class.forName("test.Student");
Annotation[] annotations = aClass.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
TableMy b = (TableMy) annotation;
String value = b.value();
System.out.println(value);
}
TableMy m = (TableMy) aClass.getAnnotation(TableMy.class);
String value = m.value();
System.out.println(value);
Field id = aClass.getDeclaredField("id");
FieldMy f = id.getAnnotation(FieldMy.class);
System.out.println(f.columnName());
System.out.println(f.type());
System.out.println(f.length());
}
}
@TableMy("tb_student")
class Student {
@FieldMy(columnName = "tb_id", type = "int", length = 10)
private int id;
@FieldMy(columnName = "tb_name", type = "varchar", length = 20)
private String name;
@FieldMy(columnName = "tb_address", type = "varchar", length = 50)
String address;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Student() {
}
public Student(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableMy {
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldMy {
String columnName();
String type();
int length();
}
|