1.引入案例支持
(1)配置servlet
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.ffyc.dormms.servlet.LoginServlet</servlet-class>
</servlet>
服务器启动时,就会创建该类的对象,使用的就是反射机制创建该类的对象
(2)mybatis
resultType="com.ffyc.mybatispro.model.Admin"
配置了哪个类,就创建出该类的对象
(3)加载mysql驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
2.什么是Java反射?
回忆一下之前如何使用一个Java类?
已知一个类的类名、以及、类中的方法属性、构造方法等
使用new关键字创建对象
使用对象调用方法或属性
为什么用反射机制?
就是像框架一样,可以写一套机制,来处理任意的类,就使得程序更急灵活,
以不变应万变.
以不变应万变.
什么是反射机制 ?
仅知道类的地址(字符串).( com.mysql.cj.jdbc.Driver )类地址
就需要在运行时,可以动态的获取任意一个类的信息,可以创建任意类的对象,调用任意对象中的方法,属性,这种动态获取类信息的功能,称为java反射机制. 称为反向使用类
Java反射的概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个
类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个
方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为
java语言的反射机制。
Java反射的作用
动态获取类的信息
Java反射相关API
Class 类型(在java.lang包中):表示一个正在运行中的类或接口
一旦一个类被加载到内存中去,都会为该类创建一个对象,可以通过该对象获取类中的信息.
要使用反射机制动态获取,创建对象,首先就是要获得类的class对象.
package com.ffyc.javareflect.model;
public class User {
private int id;
private String account;
private String password;
public User() {
System.out.println("user无参构造");
}
private User(int id, String account, String password) {
this.id = id;
this.account = account;
this.password = password;
System.out.println("有3个参构造方法");
}
public User(int id, String account) {
this.id = id;
this.account = account;
System.out.println("有2个参构造方法");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
}
package com.ffyc.javareflect.model;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//new User(); 正向使用
/*
反射的起点,就是要获得类的Class对象,获取类的信息
获取类的class对象方式有3种,无论类创建了多少个对象,一个类的class对象只有一个
*/
Class c1 = User.class;
System.out.println(c1);
Class c2 = new User().getClass();
System.out.println(c2);
//根据类的地址加载类,并获得该类的class对象
String className = "com.ffyc.javareflect.model.User";
Class c3 = Class.forName(className);
System.out.println(c3);
}
}
Constructor 构造方法
package com.ffyc.javareflect.model;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
/*
演示通过Class类的对象获取构造方法
forName();
Class类中 c.newInstance(); 也是创建对象的一种方式
Constructor类中constructor.newInstance();
*/
String className = "com.ffyc.javareflect.model.User";
Class c = Class.forName(className);
//Object object = c.newInstance();
//获取类中公共的指定的构造方法 用Constructor类的对象来表示构造方法的信息
// Constructor constructor = c.getConstructor();
// Object obj = constructor.newInstance();
//Constructor constructor = c.getConstructor(int.class,String.class,String.class );
//System.out.println(Arrays.toString(constructor.getParameters()));
//获取私有的构造方法,打破了隐蔽性
Constructor constructor = c.getDeclaredConstructor(int.class,String.class,String.class);
constructor.setAccessible(true);//开权限
constructor.newInstance(1,"jim","111");
//获得类中所有的构造方法
Constructor[] constructors = c.getDeclaredConstructors();
for (Constructor constructor1 : constructors){
if (constructor1.isAccessible()){
constructor1.setAccessible(true);
}else{
}
}
}
}
Method 方法
●
Method类将类中的方法进行封装,可以动态获得方法的信息,例如
●
getName:获得方法名字
●
getParameterTypes:获得方法参数类型
●
除了动态获得方法信息外,Method还能动态调用某一个对象的具体方法
●
invoke(Object obj, Object... args) :使用obj调用该方法,参数为args
Field 属性
●
Field类将类的属性进行封装,可以获得属性的基本信息、属性的值,也 可以对属性进行赋值.
●
getName:返回属性的名字
●
set:设置属性值
package com.ffyc.javareflect.model;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
String className = "com.ffyc.javareflect.model.User";
Class c = Class.forName(className);
Object obj = c.newInstance();//创建对象
//c.getField("account");
Field[] fields = c.getDeclaredFields();//可以获取类中的所有属性
for (Field f : fields){
System.out.println(f.getName());
System.out.println("set"+f.getName().substring(0,1).toUpperCase()+f.getName().substring(1));
//通过反射机制获取类中的方法
Method method = c.getMethod("set"+f.getName().substring(0,1).toUpperCase()+f.getName().substring(1),f.getType());
method.invoke(obj,"1111");
}
}
}
小案例
package com.ffyc.javareflect.model;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyJson {
//简单反射案例
public static String objToJson(Object obj) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String json = "{";
Class c = obj.getClass();
Field[] fs = c.getDeclaredFields();//获取到任意一个类中的所有属性
for (Field f:fs){
String name = f.getName();
json+=name+":";
Method m = c.getMethod("get"+name.substring(0,1).toUpperCase()+name.substring(1));//动态构成get方法名称,并获取到get方法
Object value = m.invoke(obj);//调用了属性的get方法
json +=value+",";
}
json = json.substring(0,json.length()-1);
json+="}";
return json;//{id:值,account:值}
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
User user = new User();
user.setId(10);
user.setAccount("admin");
user.setPassword("111");
String json = MyJson.objToJson(user);
System.out.println(json);
}
}
反射优缺点
●
优点
:
● 1.
增加程序的灵活性,可以在运行的过程中动态对类进行修改和操作
● 2.
提高代码的复用率,比如动态代理
● 3.
可以在运行时轻松获取任意一个类的方法、属性,并且还能通过反射进行动态调用
●
缺点
:
● 1.
反射会涉及到动态类型的解析,导致性能要比非反射调用更低
● 2.
使用反射技术通常要在一个没有安全限制的程序运行
.
● 3.
反射可以绕过一些限制访问的属性或者方法,可能会导致破坏代码本身的抽象性