一.java反射之详解
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/fa9b043a08483aec1eb9ffabf62a482a.png)
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));
}
}
}
运行结果
小贴士 :可以根据场景使用
制作不易,希望多多鼓励。