目录
1.回顾
在了解Java反射之前,我们需要回顾一下之前在java中如何使用类和对象。
1.定义类
public class 类名{
String name;
.....
属性
public void 方法名(){
}
}
2.创建已知类的对象,明确知道要创建哪一个类的对象
这一切都是已知的,这对于我们自己写的程序是没有问题的。
但是像框架,tomcat,或者其他的组件(jackson 对象 -->json),事先是不知道具体要处理哪些类的,
只能根据配置文件中配置的类的地址决定要创建并操作哪个类。
那么问题来了,如果我们只知道类的地址,如何使用类?
<servlet-class>com.ffyc.dormserver.web.LoginServlet</servlet-class>
<servlet-class>com.ffyc.dormserver.web.BuildServlet</servlet-class>
框架可以做到给他什么类名,就可以创建给定类的对象,并调用该对象的方法和属性。
1.创建对象
2.将查询到的结果封装到我们创建的对象中(调用setxxx() 调用xxx属性)
那如何实现写一条程序可以处理任何类呢?
答案就是反射机制。
反射机制,可以看做是一种反向使用类。
二.反射的概述
2.1Java反射的概念
Java反射机制是在运行状态,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能被称为Java语言的反射机制。
2.2Java反射的作用
动态获取类的信息
三.Class类
3.1概述
● 一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被使用时都会创建一个Class对象。
● Class类是Java反射机制的基础,通过Class类,可以得到一个类的基本 信息。
- 一个类在堆中只有一个Class对象,这个Class对象包含了类的完整结构信息
- 在使用反射的过程中,把方法、属性、构造器都当做对象来处理的
- Class类对象由系统创建,继承了Object类
3.2获取类的三种方式
3.2.1
Object类中的getClass方法:适用于1通过对象获得Class实例的情况
User user = new User();
Class class = user.getClass();//通过已知的对象中getClass()方法 获得该对象的Class对象
3.2.2
类名.class方式:适用于通过类名获得Class实例的情况
User user = new User();
Class class = User.class;
3.2.3
Class类的静态方法 forName(String name)
String s = "com.ffyc.javareflect.Demo2.User";
Class class = Class.forName(s);//把给定地址的类进行加载,为其创建class对象
四.Constructor类
4.1Constuctor方法
public String getName()
返回构造方法名
public T newInstance(Object … initargs)
创建对象【参数为创建对象的数据】
4.2具体实例
getConstructor( )
获得类中指定的公共构造方法 将获得到的无参构造方法封装到一个 Constructor对象中
getDeclaredConstructor( )
获得类中指定的构造方法(包含私有的)
getConstructors( )
获得所有公共的构造方法
getDeclaredConstructors( )
获得所有的构造方法(包含私有的)
getName( ):返回构造器的全类名
setAccessible( ):爆破,访问私有成员
newInstance( ):创建对象
package com.ffyc.javareflect.Demo2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Text3 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
String s = "com.ffyc.javareflect.Demo2.User";
//加载类,并获得Class对象
Class c = Class.forName(s);
//通过Class类的对象,来创建User对象
//Object userobject = c.newInstance();
//System.out.println(userobject);
//获取类中的构造方法信息
Constructor constructor = c.getConstructor();//获得类中指定的公共构造方法 将获得到的无参构造方法封装到一个 Constructor对象中
Object userobject = constructor.newInstance();//通过构造方法中的newInstance()创建对象
System.out.println(userobject);
Constructor constructor1 = c.getDeclaredConstructor();//获得类中指定的构造方法(包含私有的)
Constructor constructor2 = c.getConstructor(String.class,String.class);//获得公共的有参构造方法
Object userobject1 = constructor2.newInstance("111","222");//创建对象,并为对象数组赋值
System.out.println(userobject1);
Constructor[] constructors = c.getConstructors();//获得所有公共的构造方法
Constructor[] constructors1 = c.getDeclaredConstructors();//获得所有的构造方法(包含私有的)
System.out.println(constructors.length);
System.out.println(constructors1.length);
}
}
五.Field类
getField( )
获得类中指定公共的属性,把属性封装到一个Field对象中
getDeclaredField( )
获得类中指定的属性(包含私有,受保护,默认,公共),把属性封装到一个Field对象中
getFields( )
获得类中所有的公共属性
getDeclaredFields( )
获得到所有的属性(包含私有的)
getName( ):返回属性名
package com.ffyc.javareflect.Demo2;
import java.lang.reflect.Field;
public class Text4 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
String s = "com.ffyc.javareflect.Demo2.User";
Class c = Class.forName(s);//获得类的Class对象
Object userobject = c.newInstance();//创建User类的对象
//获得类中的成员变量
//获得类中指定公共的属性,把属性封装到一个Field对象中
//Field userNameField = c.getField("userName");
//获得类中指定的属性(包含私有,受保护,默认,公共),把属性封装到一个Field对象中
Field userNameField = c.getDeclaredField("userName");
//Field[] fields = c.getFields();
//System.out.println(fields.length);
//获得到所有的属性(包含私有的)
Field[] fields = c.getDeclaredFields();
System.out.println(fields.length);
//循环所有的属性,为属性赋值
for (Field f : fields){
f.setAccessible(true);//设置私有属性可以操作
f.set(userobject,"111");
}
System.out.println(userobject);
}
}
六.Method类
getMethod( )
getDeclaredMethod( )
getMethods( )
获得本类和父类所有公共的成员方法
getDeclaredMethods( )
获得本类中所有成员方法
getName( ):返回方法的名称
package com.ffyc.javareflect.Demo2;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
public class Text5 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
String s = "com.ffyc.javareflect.Demo2.User";
Class c=Class.forName(s);//获得类的Class对象
Object userobject=c.newInstance();//创建user类的对象
Method eat=c.getMethod("eat");
// 执行userobject对象中的 无参的eat方法
eat.invoke(userobject);
Method eat1=c.getMethod("eat",String.class);
eat1.invoke(userobject,"烤肉");
Method[] methods=c.getMethods();// 获得本类和父类所有公共的成员方法
Method[] methods1=c.getDeclaredMethods();// 获得本类中所有成员方法
System.out.println(methods.length);//15
System.out.println(methods1.length);//7
}
}
七.反射案例
我们可以自定义java对象转json工具类
下面是代码实例:
package com.ffyc.javareflect.util;
import com.ffyc.javareflect.Demo1.Car;
import com.ffyc.javareflect.Demo2.User;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class JasonUtil {
/*
自定义的对象转json方法 {name:"jim",age:10}
*/
public String objectToJson(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String json = "{";
Class c = object.getClass();
Field[] fields = c.getDeclaredFields();
for(Field f :fields){
//生成属性的get方法名
String get = "get"+(char)(f.getName().charAt(0)-32)+f.getName().substring(1);
Method getMethod = c.getMethod(get);//通过get方法名 获得方法
json+=f.getName()+":"+getMethod.invoke(object)+",";
}
json = json.substring(0,json.length()-1);
json+="}";
return json;
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
User user = new User();
user.setUserName("admin");
user.setPassword("111");
Car car = new Car();
car.setName("大众");
car.setColor("黑色");
System.out.println(new JasonUtil().objectToJson(user));
System.out.println(new JasonUtil().objectToJson(car));
}
}
八.反射的优缺点总结
● 优点:● 1. 增加程序的灵活性,可以在运行的过程中动态对类进行修改和操作● 2. 提高代码的复用率,比如动态代理● 3. 可以在运行时轻松获取任意一个类的方法、属性,并且还能通过反射进行动态调用● 缺点:● 1. 反射会涉及到动态类型的解析,导致性能要比非反射调用更低● 2. 使用反射技术通常要在一个没有安全限制的程序运行 .● 3. 反射可以绕过一些限制访问的属性或者方法,可能会导致破坏代码本身的抽象性