反射
总结反射是什么?
Class类
获得类的Class对象 constructor类Field类Method类
总结要用反射,先获得类的Class对象,
Class c = Class.forName(classpath);
Object user = c.newInstance();
通过Class对象获得类中的构造方法,将获得的构造方法信息,封装到一个Constructor类的对象中
Constructor constructor = c.getDeclaredConstructor();
通过Class对象获得类中的属性信息,封装到一个Field类的对象中
Field namef = c.getDeclaredField("属性");
属性是私有的,不能直接操作,通过获取属性公有的get,set方法
通过Class对象获得类中的方法,封装到一个Method类的对象中
Method m = c.getMethod("set"+String.valueOf(s.charAt(0)).toUpperCase()+s.substring(1),String.class);//setNo()
m.invoke(user,"100"); //Invoke 调用
Method m1 = c.getMethod("get"+String.valueOf(s.charAt(0)).toUpperCase()+s.substring(1));//getNo()
System.out.println(m1.invoke(user));//100
首先,大概有个反射的概念。
反射就是能够在只知道一个类名的情况下,动态获取到类的方法、属性等类中的信息,是让我们来使用的。
理解一下:只知道类名,就能知道类中的方法和属性。
这里回想下之前学的,想要调用类中的属性和方法,是怎么做的?
答:先创建一个类,定义好属性、方法、构造方法等,然后new一个对象出来,最后使用对象调用属性、方法,像下面这样:
①先创建了一个User类:
public class User {
//属性
private int no;
private String name;
//无参构造方法
public User() {
System.out.println("无参构造方法");
}
//有参构造方法
public User(int no, String name) {
this.no = no;
this.name = name;
System.out.println("有参构造方法");
}
//无参成员方法
public void eat(){
System.out.println("eat");
}
//有参成员方法
public void eat(String n){
System.out.println("有参的eat");
}
//访问私有属性的入口
public int getNo() {
System.out.println("getNo");
return no;
}
public void setNo(int no) {
System.out.println("setNo");
this.no = no;
}
public String getName() {
System.out.println("getName");
return name;
}
public void setName(String name) {
System.out.println("setName");
this.name = name;
}
}
②再new一个对象,通过对象来调用类中的方法属性:
public class Test {
public static void main(String[] args){
User user = new User();
user.eat(); //eat
user.eat("food"); //有参的eat
user.setNo(100); //set为私有属性设置值
System.out.println(user.getNo()); //get获得私有属性的值
}
}
像这样要用一个类中的方法属性,就必须得先创建好一个类,然而有没有一种方法,能够在只知道一个类名的情况下,知道类的方法属性呢?
有,这就是今天讲的——反射
那为什么反射能够在只知道一个类名的情况下,就能知道到类的方法、属性?你得是有这个问题了
这是一个问题,我也不知道!!!!!看看底层代码吧,我也看不懂
我觉得这应该是底层实现的东西,目前我们需要知道的是:怎么使用反射,来帮助我们在只知道类名的情况下,调用类中的方法属性。
那我们目前见过的反射都有啥?
//java连接mysql数据库的时候JDBC中的注册驱动,当时说这个是反射
Class.forName("com.mysql.cj.jdbc.Driver");
//web.xml文件中配置servlet和filter的时候,当时说这也是用的反射com.ffyc.webback.servlet.LoginServlet com.ffyc.webback.filter.EncodingFilter
那反射到底是个啥?
反射是什么?在运行状态中,对于任意一个类,都可以动态获取类的信息,可以调用对象中属性,方法.
这种动态获取,操作的方式称为反射机制.
我们需要了解,java反射相关的类里面有什么:
反射API:
Class 类型Constructor 构造方法 位于java.lang.reflect中Method 方法 位于java.lang.reflect中Field 属性 位于java.lang.reflect中
Class类型 ——> 反射机制基础,用反射机制,先获得类的Class对象
Constructor——>把构造方法也封装成了一个类,名字叫Constructor类
Method——>把类中的方法封装成一个类,就是Method类
Field——>把类中的属性封装成一个类,名字叫Field类
一个User类里面有的方法属性,反射中的类都有,只不过反射API将类的类型、方法、属性也都封装成了类而已。
下面分别介绍这四个反射中封装的类。
Class类java反射机制的基础,用反射机制,先获得类的Class对象。通过Class类,可以得到一个类的信息。 获得类的Class对象
package com.ffyc.webback_final.reflect.demo1;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//User user = new User();
User user = new User();
System.out.println(user); //com.ffyc.webback_final.reflect.demo1.User@7f31245a
User user1 = new User();
user.eat(); //eat
user.eat("food"); //有参的eat
user.setNo(100); //set为私有属性设置值
System.out.println(user.getNo()); //get获得私有属性的值
System.out.println("------------------------------------------------------");
Class c1 = user.getClass();
Class c2 = user1.getClass();
System.out.println(c1); //class com.ffyc.webback_final.reflect.demo1.User
System.out.println(c1==c2);
Class c3 = User.class;
System.out.println(c1==c3);
String classpath = "com.ffyc.webback_final.reflect.demo1.User";
Class c4 = Class.forName(classpath);
System.out.println(c4);
Object obj = c4.newInstance();
System.out.println(c4==c2);
}
}
constructor类
getXXX()方法获得构造方法的基本信息
getName:返回构造方法的名字创建实例 :newInstance(Object…initargs)
Constructor类的实例通过Classs实例获得
package com.ffyc.webback_final.reflect.demo1;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test2 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("com.ffyc.webback.reflect.demo1.User");
//Object user = c.newInstance();
Constructor[] cs = c.getDeclaredConstructors();//获得到类中所有的构造方法.
}
}
Field类
Field类属性封装,可以获得属性的值等信息,也可以对属性赋值。
getName:返回属性的名字Set:设置属性的值
获得Filed类的实例:通过Class类中的方法实现
package com.ffyc.webback_final.reflect.demo1;
import java.lang.reflect.Field;
public class Test3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
Class c = Class.forName("com.ffyc.webback_final.reflect.demo1.User"); //要用反射,先获得类的Class对象
System.out.println(c); //class com.ffyc.webback_final.reflect.demo1.User
Object user = c.newInstance();
System.out.println(user); //com.ffyc.webback_final.reflect.demo1.User@7f31245a
Field namef = c.getDeclaredField("no");
namef.setAccessible(true);//允许访问操作私有成员
namef.set(user,100);
System.out.println(((User)user).getNo());
}
}
Method类
Method类将类中的方法封装,可以动态获取方法的信息。
getName : 获取方法名字
getParameterType : 获得方法参数类型
除了动态获取方法信息,Method类还能动态调用某一个对象的具体方法;invoke 调用
invoke(Object obj,Object … args):使用obj调用改方法,参数为args
获得Method类的实例:通过Class类的方法获得
Method getMethod(String name,Class…parameterTypes):通过指定方法名,参数类型,返回一个Method实例
package com.ffyc.webback_final.reflect.demo1;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("com.ffyc.webback.reflect.demo1.User");
Object user = c.newInstance();
//属性是私有的,不想直接对其操作,可以获得属性的公共的get,set方法
//no
String s = "name";
Method m = c.getMethod("set"+String.valueOf(s.charAt(0)).toUpperCase()+s.substring(1),String.class);//setNo()
m.invoke(user,"100");
Method m1 = c.getMethod("get"+String.valueOf(s.charAt(0)).toUpperCase()+s.substring(1));//getNo()
System.out.println(m1.invoke(user));
}
}



