1、什么是反射:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射就是把java类中的各种成分映射成一个个的Java对象。
一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象,(一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)
2、Class类与reflect包
Java反射机制主要是 java.lang.Class类和java.lang.reflect包
2.1、Class类:
Class类是实现反射的关键所在,Class类的一个实例表示Java的一种数据类型,包括类、接 口、枚举、注解(Annotation)、数组、基本数据类型和void,void是“无类型”,主要用于方法返回值 类型声明,表示不需要返回值。Class没有公有的构造方法,Class实例是由JVM在类加载时自动创建的
得到Class类对象的三种方式:
- 类的class属性
- getClass()方法
- 类的完全限定名
public class MainTest {
public static void main(String[] args) throws Exception {
//User是一个自己创建的类
//方式一:通过class输出
Class c1=User.class;
//方式二:getClass()方法
User user=new User();
Class c2=user.getClass();
//方式三:通过类的完全限定名(内置路径):包名.类名
Class c3=Class.forName("three.User");
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
//比较特殊的数据类型:
Class c4 = int.class;
Class c5 = double.class;
Class c6 = long.class;
Class c7 = short.class;
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
}
}
2.2:reflect包:
java.lang.reflect包提供了反射中用到类,主要的类说明如下:
- Constructor类:提供类的构造方法信息。
- Field类:提供类或接口中成员变量信息。
- Method类:提供类或接口成员方法信息。
- Array类:提供了动态创建和访问Java数组的方法。
- Modifier类:提供类和成员访问修饰符信息
常用到的方法与对应类如下:
Constructor类:提供类的构造方法信息,
Field类:提供类或接口中成员变量信息。
Method类:提供类或接口成员方法信息。
Array类:提供了动态创建和访问Java数组的方法。
Modifier类:提供类和成员访问修饰符信息
3、获取方法信息
用于实验的类Student:
public class Student {
private String name ="admin";
public int age = 18;
protected String email = "sfss@qq.com";
private Student(String name) {
super();
this.name = name;
}
public Student(String name, int age, String email) {
super();
this.name = name;
this.age = age;
this.email = email;
}
private Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String toString() {
return "Student [name=" + name + ", age=" + age + ", email=" + email + "]";
}
public Student() {
super();
}
public static void show() {
System.out.println("大家下午好!");
}
protected void sayHi() {
System.out.println("hello!");
}
private void hello(String msg) {
System.out.println("hello!"+msg);
}
}
3.1获取公有方法的对象:getMethods()
getMethods():可以得到本类和父类中的所有的公有的方法,返回Method类型的素组,
import java.lang.reflect.Method;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
//得到Student类中的公有方法信息
Method[] methods = c.getMethods();//getMethods():它可以得到Student为中和父类中的所有的公有的方法,非公有的就得不到了
for (Method method : methods) {
System.out.println(method);
}
}
}
3.2构造方法:
a、获取构造方法:
getDeclaredConstructors():得到全部的构造器信息
getConstructors():只能得到公有的构造器信息
getDeclaredConstructor(): 获取public修饰的构造函数(单个)
import java.lang.reflect.*;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
Constructor []con= c.getDeclaredConstructors();//全部的构造器信息
//Constructor []con= c.getConstructors();//只能得到公有的构造器信息
for (Constructor constr : con) {
System.out.println(constr);
}
}
}
结果
获取public修饰的构造函数(单个):getDeclaredConstructor()
b、调用私有的构造方法:
import java.lang.reflect.*;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
Constructor cons = c.getDeclaredConstructor(String.class);
cons.setAccessible (true);// 暴力访问 setAccessible方法是是否可访问
Object obj = cons.newInstance("西门庆"); // newInstance:创建对象,等价于new Student("西门庆")
System.out.println(obj);
}
}
3.3调用指定方法:
a、调用无参的指定方法
import java.lang.reflect.*;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
Method method = c.getDeclaredMethod("show");//指定show方法
//执行一下该方法
Object obj = c.getConstructor().newInstance();//实例化一个Student类的实例
method.invoke(obj);//调用Student的show方法,invoke()就是调用类中的方法
}
}
b、 调用有参的指定方法:
import java.lang.reflect.*;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
Method method = c.getDeclaredMethod("hello",String.class);
Object obj = c.getConstructor().newInstance();
method.setAccessible(true); //暴力访问
method.invoke(obj,"张三");
}
}
3.4判断指定方法是公有,还是私有
import java.lang.reflect.*;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
Method method = c.getDeclaredMethod("show");
int mod = method.getModifiers();
System.out.println("是私有吗:"+Modifier.isPrivate(mod));
System.out.println("是公有吗:"+Modifier.isPublic(mod));
}
}
4、获取属性
4.1:获取全部属性的对象
import java.lang.reflect.*;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
Field [] f=c.getDeclaredFields();
for(Field field:f) {
System.out.println(field);
}
}
}
4.2 获取指定公共属性的对象,或获取指定私有属性的对象
import java.lang.reflect.*;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
Field f=c.getField("age");//获取指定的公共属性
System.out.println(f);
Field f1=c.getDeclaredField("name");//获取指定的私有属性
System.out.println(f1);
}
}
4.3 修改属性
import java.lang.reflect.*;
public class MainTest {
public static void main(String[] args) throws Exception {
Class c = Class.forName("three.Student");//得到类对象
Constructor con= c.getConstructor();
Object obj = con.newInstance();//实力化对象
Field field = c.getField("age"); // 获取单个字段
field.set(obj, 30);// 设置值
System.out.println(obj);
}
}
5、操作数组
import java.lang.reflect.Array;
public class One {
public static void main(String[] args) {
//普遍建立数组的方式:
int[] nums = new int[3]; //方式1
int nums2[] = new int[3]; //方式2
int[] nums3 = new int[]{1,2,3}; //方式3
int[] nums4 = {2,3,4,5}; //方式4
//使用反射Array类来实现
Object arr = Array.newInstance(int.class, 4); //创建一个长度为4的int类型数组
//增加元素
Array.setInt(arr, 0, 100);
Array.setInt(arr, 1, 200);
Array.setInt(arr, 2, 300);
Array.setInt(arr, 3, 400);
//遍历数组中的元素
for (int i = 0; i < Array.getLength(arr); i++) {
Object value = Array.get(arr, i);//获得当前元素
System.out.print(value+",");
}
}
}