目录
1.回顾
二.反射的概述
2.1Java反射的概念
2.2Java反射的作用
三.Class类
3.1概述
3.2获取类的三种方式
3.2.1
3.2.2
3.2.3
四.Constructor类
4.1Constuctor方法
4.2具体实例
五.Field类
六.Method类
七.反射案例
八.反射的优缺点总结
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);//15System.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. 反射可以绕过一些限制访问的属性或者方法,可能会导致破坏代码本身的抽象性