1.什么是反射?
1.在Java中,反射是指程序在运行时可以观察和修改自己的行为的能力。反射使得程序可以动态地获取类型信息、访问对象的属性和方法,并调用方法,而不需要提前在代码中编写对应的静态类型和调用代码。借助反射,程序可以在运行时动态地加载和使用类,而不需要在编译时知道有哪些类存在。反射常用于框架开发、插件化和动态代理等场景。在Java中,反射API包括java.lang.reflect包中的类和接口,这些API允许程序获取类型信息、构造类实例、访问和修改字段和方法等。
2. 反射中类类的含义与概念
1.前言
Java反射机制提供了一组API,用于在运行时检查、访问和修改类、接口、字段、方法和构造函数的信息。Java反射API包括在java.lang.reflect包中定义的一些接口和类,这些接口和类提供了以下功能:
1.Class类:
Class类是Java反射的核心类,它用于表示一个类或接口的类型信息。通过Class类,可以获取一个类的所有元素信息,包括字段、方法、构造函数、父类和实现的接口等。
2.Constructor类
Constructor类:Constructor类提供了对类的构造函数的访问和调用。它允许我们使用类的构造函数创建对象实例,并提供了对构造函数参数的访问。
3.Method类
Method类:Method类提供了对方法的访问和调用。它允许我们在运行时执行类中定义的方法,并提供了对方法参数和返回值的访问。
4.Field类
Field类:Field类提供了对字段的访问和修改。它允许我们获取或设置类的成员变量的值。
5.Modifier类
Modifier类:Modifier类用于获取和修改字段、方法和类的修饰符,例如public、private、static等。
使用Java反射机制,程序可以在运行时动态获取和修改类、接口、字段和方法等的信息,从而使得代码更加灵活和扩展性更强,在某些场景下比静态编码更有优势。反射虽然功能强大,但也会带来性能损失和安全问题,因此在使用反射时需要谨慎权衡利弊。
1.示例
接下来,会以下面student类,为示例进行各种演示,助力你们理解,反射。
package com.niyin.reflection; public class Student { private String sid; private String sname; public Integer age; static{ System.out.println("加载进jvm中!"); } public Student() { super(); System.out.println("调用无参构造方法创建了一个学生对象"); } public Student(String sid) { super(); this.sid = sid; System.out.println("调用带一个参数的构造方法创建了一个学生对象"); } public Student(String sid, String sname) { super(); this.sid = sid; this.sname = sname; System.out.println("调用带二个参数的构造方法创建了一个学生对象"); } @SuppressWarnings("unused") private Student(Integer age) { System.out.println("调用Student类私有的构造方法创建一个学生对象"); this.age = age; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public void hello() { System.out.println("你好!我是" + this.sname); } public void hello(String name) { System.out.println(name + "你好!我是" + this.sname); } @SuppressWarnings("unused") private Integer add(Integer a, Integer b) { return new Integer(a.intValue() + b.intValue()); } }
3.反射实例化,Constructor
1.调用无参构造方法
package com.niyin.reflection; import java.lang.reflect.Constructor; /** * * @author 匿瘾 * */ public class Demo1 { public static void main(String[] args) throws Exception { Class c = Class.forName("com.niyin.reflection.Student"); Student s1 = (Student) c.newInstance(); System.out.println(s1); } }
运行结果
2.调用一个参数的
package com.niyin.reflection; import java.lang.reflect.Constructor; /** * * @author 匿瘾 * */ public class Demo1 { public static void main(String[] args) throws Exception { Class c = Class.forName("com.niyin.reflection.Student"); // System.out.println(s1); //调用有一个参数的,的方法 Constructor cr1=c.getConstructor(String.class); // Student s2 = (Student) cr1.newInstance("s001"); System.out.println(s2); } }
运行结果
3.调用两个参数的
package com.niyin.reflection; import java.lang.reflect.Constructor; /** * * @author 匿瘾 * */ public class Demo1 { public static void main(String[] args) throws Exception { Class c = Class.forName("com.niyin.reflection.Student"); Student s1 = (Student) c.newInstance(); Constructor cr2=c.getConstructor(String.class,String.class); Student s3 = (Student) cr2.newInstance("s002","nb"); System.out.println(s3); } }
运行结果
4.调用私有化的
package com.niyin.reflection; import java.lang.reflect.Constructor; /** * * @author 匿瘾 * */ public class Demo1 { public static void main(String[] args) throws Exception { Class c = Class.forName("com.niyin.reflection.Student"); Student s1 = (Student) c.newInstance(); Constructor cr3=c.getDeclaredConstructor(Integer.class); cr3.setAccessible(true); Student s4=(Student) cr3.newInstance(18); System.out.println(s4); } }
运行结果
想要调用私有,主要是通过 cr3.setAccessible(true);
打开权限。
4.反射方法的调用,Method
1.前言
1.method介绍
两个参数,name:方法名,parameterTypers:调用方法所需要传的类型
2.invoked介绍
两个参数
obj:类实例
args:参数值
invoke()方法的返回值是该方法的返回值,如果该方法是void类型,则返回null。
1.调用无参构造方法
package com.niyin.reflection; import java.lang.reflect.Method; public class Demo2 { public static void main(String[] args) throws Exception { Class c = Student.class; Student stu = (Student) c.newInstance(); Method m1 = c.getMethod("hello"); Object invoke = m1.invoke(stu); System.out.println(invoke); } }
运行结果
2.调用一个参数的方法
package com.niyin.reflection; import java.lang.reflect.Method; public class Demo2 { public static void main(String[] args) throws Exception { Class c = Student.class; Student stu = (Student) c.newInstance(); Method m2 = c.getMethod("hello", String.class); Object invoke1 = m2.invoke(stu, "你好"); System.out.println(invoke1); } }
运行结果
3.调用私有的方法
package com.niyin.reflection; import java.lang.reflect.Method; public class Demo2 { public static void main(String[] args) throws Exception { Class c = Student.class; Student stu = (Student) c.newInstance(); Method m3 =c.getDeclaredMethod("add", Integer.class,Integer.class); m3.setAccessible(true); Object invoke2 = m3.invoke(stu, 1,2); System.out.println(invoke2); } }
运行结果
提升:记得打开m3.setAccessible(true);
5.反射读取属性
1.java中反射读取属性与用get方法获取属性的区别
在Java中,有两种途径可以读取对象的属性:反射和使用getter方法。
反射可以使用Field类来获取实例中的属性值,然后对其进行操作。这种方法的优点是可以直接读取或设置对象的私有属性,并可以根据程序运行时的条件来决定读取哪一个对象的属性。但缺点是反射效率相对较低,而且更容易出错,例如当属性名更改时,编译时不会出现错误,但运行时会因为找不到原先的属性而抛出异常。
而使用getter方法则是通过公共方法来获取属性值,这种方法使用了封装和控制属性访问的思想,可以使代码更加健壮且易于维护。缺点是如果想要读取私有属性,则必须在类中提供相应的public方法,否则无法直接获取。
因此,如果需要对属性进行访问或修改,推荐使用getter方法;如果需要在程序运行时动态地访问属性值或直接访问私有属性,可以使用反射。在实际开发中,需要根据具体的场景来确定应该采用哪种方式。
示例
1.get方法获取
package com.niyin.reflection; import java.lang.reflect.Field; public class Demo3 { public static void main(String[] args) throws Exception{ Class clz =Student.class; Student stu =new Student("s001","nv"); System.out.println(stu.getSid() ); System.out.println(stu.getSname()); } } }
运行结果
2.反射读取属性
package com.niyin.reflection; import java.lang.reflect.Field; public class Demo3 { public static void main(String[] args) throws Exception{ Class clz =Student.class; Student stu =new Student("s001","nv"); Field[] declaredFields = clz.getDeclaredFields(); for (Field f : declaredFields) { f.setAccessible(true); System.out.println(f.getName()+":" +f.get(stu)); } } }
运行结果
小贴士 :可以根据场景使用
制作不易,希望多多鼓励。