[ Java 反射机制 ]
目录
一. 概述
1. 前提
2.定义:
3.作用:
4.如何获取类信息:
5. Class类
1. 获得任意类的class对象
2. Java中创建对象的方式
3.通过Class类获得类中属性
4. 通过Class类对象 获得类中的方法
5.举例
6. 反射的优缺点
(1)优点:
(2)缺点:
一. 概述
1. 前提
已知一个类,通过new创建这个类的对象, 使用对象去调用属性和方法. 用哪个对象,就在代码中new
在业务代码中这样写没有问题,而对于框架来说,这样写就不行了.
由于框架要处理项目中任意的类,为任意类创建出一个实例(对象)
所以框架需要满足一套机制,即只需要写一套代码,就可以创建任意类对象
在接触框架之后, 用法就发生了一些变化:
2.定义:
程序在运行时只需要知道字符串类地址,就可以创建该类的对象,能够动态获取类信息,动态创建对象,并且能够调用任意对象的方法或操作其属性的机制称为Java的反射机制
3.作用:
根据类的地址(字符串类地址"com.ffyc.news.model.Admin"),动态获得类信息,动态创建对象,调用对象的属性和方法
4.如何获取类信息:
java.long.Class 类
在方法区中(存储类信息) , 为每一个类创建一个class类的对象,可以通过class类的对象获取他所表示的类中的任何信息
一个Class类对象表示一个运行时的Java类信息,我们可以通过class类提供的方法,获取类中的信息,并创建类的对象,所有Class类是Java反射机制的根基
Class-----类型 Method------方法 Filed------属性
5. Class类
1. 获得任意类的class对象
(1).已知类的字符串地址 Class.forName();
(2).类名.class
(3).对象名.getClass()
package com.ffyc.javareflect;public class User {private String account;private String password;public String phone;public String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public User(){System.out.println("user无参构造方法");}public User(String account, String password, String phone) {this.account = account;this.password = password;this.phone = phone;}public void eat(){System.out.println("无参eat");}public void eat(String foodName){System.out.println("有参的eat");}public String getAccount() {return account;}public void setAccount(String account) {this.account = account;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}
}
package com.ffyc.javareflect;public class Test1 {public static void main(String[] args) throws ClassNotFoundException {/*传统的类使用:User user = new User();//已知有一个user类,我们创建该类的对象对于框架来说,面对当得可能是未知的*//*获得任意类的class对象*///方式一:已知类的字符串地址String className ="com.ffyc.javareflect.User";//框架常用Class a= Class.forName(className);System.out.println(a);//方式二:类名.classClass b= User.class;//mybatis 中使用 接口.方法System.out.println(b);//方式三: 对象名.getClass()User user = new User();Class c = user.getClass();//把当前类型转为Class类型System.out.println(b==a);//true 地址相同System.out.println(c==a);//true 地址相同System.out.println(b==c);//true 地址相同}
}
2. Java中创建对象的方式
1.new对象
2.io中 对象输出流(反序列化)
3.反射机制 通过Class类对象中的newInstance();
4.对象克隆
3.通过Class类获得类中属性
getField("Phone") 获取类中指定的公共属性
getFields() 获得类中所有的公共属性
getDeclaredFields() 获得类中所有的属性
package com.ffyc.javareflect;import java.lang.reflect.Field;public class Test2 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {String className ="com.ffyc.javareflect.User";//获得类的class对象Class cl =Class.forName(className);//调用 Class类中的newInstance() 还会调用类中无参的构造方法,创建出一个对象Object obj = cl.newInstance();System.out.println(obj);//输出对象/*通过Class类获得类中属性getField("Phone") 获取类中指定的公共属性getFields() 获得类中所有的公共属性getDeclaredFields() 获得类中所有的属性*/Field accField = cl.getField("account");System.out.println(accField);//拿不到,因为account是私有的,只能拿公共的Field[] pubfields = cl.getFields();System.out.println(pubfields.length);for(Field field:pubfields){field.set(obj,"aaa");System.out.println(field);}Field[] fields = cl.getDeclaredFields();for(Field field:fields){System.out.println(field);//输出所有属性field.setAccessible(true);//设置对私有属性是否可以操作的开关,默认关闭field.set(obj,"aaaa");//给属性赋值System.out.println(field.get(obj));//拿到属性的值}}
}
4. 通过Class类对象 获得类中的方法
getMethods() 获得类中所有的公共方法
package com.ffyc.javareflect;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class Test3 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {/*Java中创建对象的方式1.new对象2.io中 对象输出流(反序列化)3.反射机制 Class类中的newInstance();4.对象克隆*/String className ="com.ffyc.javareflect.User";//获得类的class对象Class cl =Class.forName(className);//调用 Class类中的newInstance() 还会调用类中无参的构造方法,创建出一个对象Object obj = cl.newInstance();/*通过Class类对象 获得类中的方法getMethods() 获得类中所有的公共方法*/Method method = cl.getMethod("eat");System.out.println(method);//拿到无参的eat方法method.invoke(obj);//调用获得的方法//getMethod("方法名",参数类型) 获得指定方法名 指定类型的公共成员方法Method method1= cl.getMethod("eat",String.class);System.out.println(method1);method1.invoke(obj,"凉皮");//给所调用的有参的方法传参}
}
5.举例
forName()
newInstance()
getField("phone"); 获得类中指定名称的公共属性
getFields(); 获得类中所有的公共属性
getDeclaredFields(); 获得类中所有属性
getDeclaredFields("phone")
getDeclaredMethods() 获得类中所有的成员方法
getMethods() 获得类中所有公共的成员方法
getMethod("eat");
getDeclaredMethod("eat");
package com.ffyc.javareflect;import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;public class Demo1 {/*模拟mybatis 自动数据封装*/public static void putData(String classname, Map<String, Object> map) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {//获得传入的类地址的class对象Class cl = Class.forName(classname);//创建一个传入类的对象Object obj = cl.newInstance();//动态获得类中的属性Field[] fields =cl.getDeclaredFields();for(Field field: fields){//首先获得属性名称(account password color....)String name = field.getName();System.out.println(name);//通过属性的名字找到属性的set方法名String methodName ="set"+(char)(name.charAt(0)-32)+(name.substring(1));System.out.println(methodName);//通过set方法名字获得对应的set方法Method setmethod = cl.getMethod(methodName,field.getType());setmethod.invoke(obj,map.get(name));//调用方法 赋值}System.out.println(obj);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {//map模拟数据库中查询到到的数据Map<String,Object> map = new HashMap<>();map.put("account","admin");map.put("password","111");map.put("phone","17511111111");//classname 模拟resultTypeString classname = "com.ffyc.javareflect.User";Demo1.putData(classname,map);Map<String,Object> map1 = new HashMap<>();map.put("name","宝马");map.put("color","红色");//classname 模拟resultTypeString classname1 = "com.ffyc.javareflect.Car";Demo1.putData(classname1,map1);}}
6. 反射的优缺点
(1)优点:
通过反射机制,可以动态获得任意类中的信息,调用任意对象中的方法,增加程序编写的灵活性和代码的复用性 例如框架 -----写一套代码就可以处理任意类 ; 公共组件...
(2)缺点:
反射机制使用效率低,可以对私有成员进行操作,打破封装性,使用反射机制时,应该尽量避对私有成员进行操作