[ Java 反射机制 ]
目录
一. 概述
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);
//方式二:类名.class
Class 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 模拟resultType
String classname = "com.ffyc.javareflect.User";
Demo1.putData(classname,map);
Map<String,Object> map1 = new HashMap<>();
map.put("name","宝马");
map.put("color","红色");
//classname 模拟resultType
String classname1 = "com.ffyc.javareflect.Car";
Demo1.putData(classname1,map1);
}
}
6. 反射的优缺点
(1)优点:
通过反射机制,可以动态获得任意类中的信息,调用任意对象中的方法,增加程序编写的灵活性和代码的复用性 例如框架 -----写一套代码就可以处理任意类 ; 公共组件...
(2)缺点:
反射机制使用效率低,可以对私有成员进行操作,打破封装性,使用反射机制时,应该尽量避对私有成员进行操作
更多推荐

所有评论(0)