反射
难点总结:
1.例子入手
package test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class ListToModel {
public static void main(String[] args) {
List<Object> userList = new ArrayList<Object>();
userList.add("tom");
userList.add("男");
userList.add(18);
User user = new User();
try {
listToModel(userList, user);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(user.getName() + "; " + user.getGender() + "; " + user.getAge());
}
//把list内容逐个取出来放进User实体类中
public static <T> void listToModel(List<Object> list, T t) throws Exception {
Field[] fields = t.getClass().getDeclaredFields();
if (list.size() != fields.length) {
return;
}
for (int k = 0, len = fields.length; k < len; k++) {
// 根据属性名称,找寻合适的set方法
String fieldName = fields[k].getName();
String setMethodName = "set" + fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
Method method = null;
Class<?> clazz = t.getClass();
try {
method = clazz.getMethod(setMethodName, new Class[] { list.get(k).getClass() });
System.out.println("list.get("+k+").getClass():"+list.get(k).getClass());
} catch (SecurityException e1) {
e1.printStackTrace();
return;
} catch (NoSuchMethodException e1) {
String newMethodName = "set" + fieldName.substring(0, 1).toLowerCase()
+ fieldName.substring(1);
try {
method = clazz.getMethod(newMethodName, new Class[] { list.get(k).getClass() });
} catch (SecurityException e) {
e.printStackTrace();
return;
} catch (NoSuchMethodException e) {
e.printStackTrace();
return;
}
}
if (method == null) {
return;
}
method.invoke(t, new Object[] { list.get(k) });
}
}
}
class User{
private String name;
private String gender;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2. Object.getClass()方法是啥?
作用
拿到反射的类
例子
User user = new User();
System.out.println(user.getClass());
控制台打印结果
class test.User
3. getDeclaredFields()
作用
拿到所有声明的成员变量集合,无论public还是private,当然是Field[] fields
例子
4. getMethod()
作用
Method Class.getMethod(String name, Class<?>… parameterTypes)的作用是获得对象所声明的公开方法
该方法的第一个参数name是要获得方法的名字,第二个参数parameterTypes是按声明顺序标识该方法形参类型,白话就是原来那个函数的参数s写成数组。
返回结果是 Method method
例子
method = clazz.getMethod(setMethodName, new Class[] {list.get(k).getClass()});
System.out.println("method:"+method);
结果:
method : public void month8day16.User.setGender(java.lang.String)
5. method.invoke()
作用
public Object invoke(Object obj, Object... args)
obj - 调用底层方法的对象。就是执行方法的对象
args - 用于方法调用的参数。就是方法要用到的实际参数
例子
method.invoke(t, new Object[] {list.get(k)})
上面的method是user的set方法,将值放入方法中,确实get得到值
date:2022/03/01
啥是反射
动态语言可以运行时改变自身结构
java通过反射可以变为准动态语言,但也增加了不安全性。
Class类用来管理反射。
应用
动态代理
在运行时判断对象所属的类
在运行时构造一个类的对象
在运行时判断一个类所有的变量和方法
在运行是调用一个对象的方法
优缺点
优点:可以动态创建编译对象
缺点:性能较弱。反射是一种解释操作,让jvm来操作。
Class类
每个类编译完成时候,都会产生Class对象。
反射获取类实际例子,一般有三种方式
1.Class.forname(“类路径”);
2.Class classTest = 目标类.class
3.Class classTest = 目标类实例对象.getClass()
类加载步骤:
- 1.方法区里面加载一个类对应Class对象
- 2.然后程序栈里面进行link过程
- 3.初始化
通过reflection获得一个对象
例子:
package com.day301.reflectiondemo;
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, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
Class c1 =Class.forName("com.day301.reflectiondemo.Userme");
Constructor constuctor = c1.getDeclaredConstructor(String.class,int.class,double.class);
//通过构造器调用对象有参构造方法,生成对象
Userme user01 = (Userme) constuctor.newInstance("shi",01,59.63);
System.out.println(user01.getAge());
Userme c2 = (Userme)c1.newInstance();
System.out.println(c2);
//默认生成无参构造方法
Method method = c1.getDeclaredMethod("setAge", double.class);
method.invoke(c2, 37.09);
System.out.println(c2.getAge());
//返回一个method,注意的是,需要将方法invoke初始化
Userme c3 = (Userme)c1.newInstance();
Field name =c1.getDeclaredField("name");
name.setAccessible(true);
name.set(c3, "我要调用方法"
+ "没错哦");
System.out.println(c3.getName());
//update field方法,需要注意的是,需要添加setAccessible(True),private filed才能修改
}
}
结果:
59.63
com.day301.reflectiondemo.Userme@3dfc5fb8
37.09
我要调用方法没错哦
性能
package com.day301.reflectiondemo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test10 {
public static void test01(){
Userme user = new Userme();
long starttime =System.currentTimeMillis();
for(int i=0;i<1000000000;i++) {
user.getName();
}
long endTime =System.currentTimeMillis();
System.out.println("默认方法"+(starttime-endTime)+"ms");
}
public static void test02() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Userme user = new Userme();
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("这是正常反射操时间: "+(starttime-endTime)+"ms");
}
public static void test03() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Userme user = new Userme();
Class c2 =user.getClass();
Method getName =c2.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(starttime-endTime+"ms");
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
test01();
test02();
test03();
}
}
结果:
默认方法-3ms
这是正常反射操时间: -1196ms
-868ms
泛型
public class TestFanxing {
public void test01(Map<String , Userme> map,List<Userme> list) {
System.out.println("调用了Test01方法");
}
public Map<String ,Userme> test02(){
System.out.println("调用了Test02方法");
return null;
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
{Method method = TestFanxing.class.getMethod("test01", Map.class,List.class);
System.out.println(method);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for(Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for(Type actual:actualTypeArguments) {
System.out.println(actual);
}
}
}}
{Method method2 = TestFanxing.class.getMethod("test02", null);
System.out.println(method2);
Type[] genericParameterTypes = method2.getGenericParameterTypes();
for(Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for(Type actual:actualTypeArguments) {
System.out.println(actual);
}
}
}
}
}
}
public void com.day301.reflectiondemo.TestFanxing.test01(java.util.Map,java.util.List)
java.util.Map<java.lang.String, com.day301.reflectiondemo.Userme>
class java.lang.String
class com.day301.reflectiondemo.Userme
java.util.List<com.day301.reflectiondemo.Userme>
class com.day301.reflectiondemo.Userme
public java.util.Map com.day301.reflectiondemo.TestFanxing.test02()
注解与反射映射成ORM
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
Class c1 = Class.forName("com.total.day301.Student");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
TableLipp tableLipp = (TableLipp) c1.getAnnotation(TableLipp.class);
String value = tableLipp.value();
System.out.println(value);
Field f =c1.getDeclaredField("id");
FieldLipp annotation = f.getAnnotation(FieldLipp.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
package com.total.day301;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@TableLipp("db_student")
public class Student {
@FieldLipp(columnName="db_id",type="int",length=10)
private int id;
@FieldLipp(columnName="db_age",type="int",length=10)
private int age;
@FieldLipp(columnName="db_name",type="varchar",length=10)
private String 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 "Student [id=" + id + ", age=" + age + ", name=" + name + "]";
}
public Student(int id, int age, String name) {
super();
this.id = id;
this.age = age;
this.name = name;
}
public Student() {
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableLipp{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldLipp{
String columnName();
String type();
int length();
}
result:
@com.total.day301.TableLipp(value="db_student")
db_student
db_id
int
10