视频链接:https://www.bilibili.com/video/BV1Rx411876f?p=1
视频范围P823 - P833
目录描述
1.获取反射属性Field
学生类:
package bean;
public class Student {
//Field翻译为字段,其实就是属性/成员
//5个Field,分别采用了不同的访问控制权限修饰符
public int no;//Field对象
private String name;//Field对象
protected int age;
boolean sex;
public static final double MATH_PI = 3.1415926;
}
测试类:
package Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectTest05 {
public static void main(String[] args) throws Exception{
//获取整个类
Class studentClass = Class.forName("bean.Student");
//获取完整类名
String className = studentClass.getName();
System.out.println("完整类名:" + className);
//获取简单类名
String simpleName = studentClass.getSimpleName();
System.out.println("简类名:" + simpleName);
//获取类中所有的public修饰的Field
Field[] fields = studentClass.getFields();
System.out.println(fields.length);//测试数组中只有2个元素
//取出这个Field
Field f = fields[0];
//取出这个Field的名字
String fieldName = f.getName();
System.out.println(fieldName);//输出为:no
//获取所有的Field
Field[] fs = studentClass.getDeclaredFields();
System.out.println(fs.length);//输出为:5
System.out.println("------------------------");
for (Field field : fs){
//获取属性的修饰符列表
int i = field.getModifiers();//返回的修饰符是一个数字,每个数字是修饰符的代号!
System.out.println(i);
//可以将这个”代号“数字转换成”字符串“
String modifierString = Modifier.toString(i);
System.out.println(modifierString);
System.out.println("- - - - - ");
//获取属性的类型
Class fieldType = field.getType();
//String fName = fieldType.getName();
//获取简单名字
String fName = fieldType.getSimpleName();
System.out.println(fName);
System.out.println("- - - - - ");
//获取属性的名字
System.out.println(field.getName());
System.out.println("+++++++++++++++++++++++++++");
}
}
}
运行结果:
2.反编译Field
通过反射机制,反编译一个类的属性Field
package Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectTest06 {
public static void main(String[] args) throws Exception{
//创建这个是为了拼接字符串
StringBuilder s = new StringBuilder();
Class studentClass = Class.forName("bean.Student");
//s.append("public class Student {");
s.append(Modifier.toString(studentClass.getModifiers()) + " class " + studentClass.getSimpleName() +" {\n");
Field[] fields = studentClass.getDeclaredFields();
for (Field field : fields){
s.append("\t");
s.append(Modifier.toString(field.getModifiers()));
s.append(" ");
s.append(field.getType().getSimpleName());
s.append(" ");
s.append(field.getName());
s.append(";\n");
}
s.append('}');
System.out.println(s);
}
}
运行结果:
3.通过反射机制访问对象属性【重要!!!】
给属性赋值set
获取属性的值get
反射机制让代码复杂了,但是为了一个“灵活”,这也是值得的
package Reflect;
import bean.Student;
import java.lang.reflect.Field;
public class ReflectTest07 {
public static void main(String[] args) throws Exception{
//不使用反射机制,去访问一个对象的属性
Student s = new Student();
//给属性赋值
s.no = 1111;//三要素:给s对象的no属性赋值1111
//读属性值
System.out.println(s.no);//两要素:获取s对象的no属性的值
//使用反射机制,访问一个对象的属性(set get)
Class studentClass = Class.forName("bean.Student");
Object obj = studentClass.newInstance();//obj就是Student对象(底层调用无参数构造方法)
//获取no属性(根据属性的名称来获取Field)
Field noField = studentClass.getDeclaredField("no");
//给obj对象(Student对象)的no属性赋值
noField.set(obj,2222);//三要素:给obj对象的no属性赋值2222
//读取属性的值
System.out.println(noField.get(obj));//两个要素:获取obj对象的no属性的值
//###################################################################
//访问私有的属性
Field nameField = studentClass.getDeclaredField("name");
//打破封装(反射机制的缺点:打破封装,可能会给不法分子留下机会!!!)
//这样设置完之后,在外部也是可以访问private的
nameField.setAccessible(true);
//给name属性赋值
nameField.set(obj,"jackson");
//获取name属性的值
System.out.println(nameField.get(obj));
}
}
4.可变长度参数
- 可变长度参数:int… args
- 语法:类型… 【注意:一定是3个点】
- 可变长度参数要求的参数个数是:0~N个
- 可变长度参数在参数列表中必须在最后一个位置上,而且可变长度参数只能有1个
- 可变长度参数可以当做一个数组来看待
package Reflect;
public class ArgsTest {
public static void main(String[] args) {
m();
m(10);
m(10,20);
//编译报错
//m("abc");
m2(100);
m2(200,"abc");
m2(200,"abc","def");
m2(200,"abc","def","xyz");
m3("ab","de","kk","ff");
String[] strs = {"a","b","c"};
//也可以传一个数组
m3(strs);
//直接传一个数组
m3(new String[]{"我","是","中","国","人"});//没必要
m3("我","是","中","国","人");
}
public static void m(int... args){
System.out.println("m方法执行了!");
}
//必须在最后一个位置上,而且可变长度参数只能有1个
//public static void m2(int... args2,String... args1){};
public static void m2(int a,String... args1){};
public static void m3(String... args){
//args有length属性,说明args是一个数组!
//可以将可变长度参数当做一个数组来看
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
运行结果:
5.反射Method
用户业务类:
package service;
public class UserService {
/**
* 登录方法
* @param name 用户名
* @param passward 密码
* @return true表示登录成功,false表示登录失败
*/
public boolean login(String name,String passward){
if ("admin".equals(name) && "123".equals(passward)){
return true;
}
return false;
}
/**
* 退出系统的方法
*/
public void logout(){
System.out.println("系统已经安全退出!");
}
}
测试类:
package Reflect;
import javax.xml.transform.Source;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectTest08 {
public static void main(String[] args) throws Exception {
//获取类
Class userServiceClass = Class.forName("service.UserService");
//获取所有的Method(包括私有的!)
Method[] methods = userServiceClass.getDeclaredMethods();
System.out.println(methods.length);//2
//遍历Method
for (Method method : methods){
//获取修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
//获取方法的返回值类型
System.out.println(method.getReturnType().getSimpleName());
//获取方法名
System.out.println(method.getName());
//方法的修饰符列表(一个方法的参数可能会有多个)
Class[] parameterTypes = method.getParameterTypes();
for (Class parameterType : parameterTypes){
System.out.println(parameterType.getSimpleName());
}
}
}
}
运行结果:
6.反编译Method
package Reflect;
import service.UserService;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectTest09 {
public static void main(String[] args) throws Exception{
StringBuilder s = new StringBuilder();
Class UserServiceClass = Class.forName("service.UserService");
s.append(Modifier.toString(UserServiceClass.getModifiers()) + " class " + UserServiceClass.getSimpleName() +" {\n");
Method[] methods = UserServiceClass.getDeclaredMethods();
for (Method method: methods){
//public boolean login(String name,String passward){}
s.append("\t");
s.append(Modifier.toString(method.getModifiers()));
s.append(" ");
s.append(method.getReturnType().getSimpleName());
s.append(" ");
s.append(method.getName());
s.append("(");
//参数列表
Class[] parameterTypes = method.getParameterTypes();
for (Class parameterType : parameterTypes){
s.append(parameterType.getSimpleName());
s.append(",");
}
//删除指定下标位置上的字符
if (parameterTypes.length > 0){
s.deleteCharAt(s.length() - 1);
}
s.append("){}\n");
}
s.append("}");
System.out.println(s);
}
}
运行结果:
7.反射机制调用方法【重要!!!】
Java中区分一个方法:依靠方法名和参数列表
反射机制优点:让代码很具有通用性,可变化的内容都是写到配置文件当中,将来修改配置文件之后,创建的对象不一样了,调用的方法也不同了,但是Java代码不需要做任何改动!
package Reflect;
import service.UserService;
import java.lang.reflect.Method;
public class ReflectTest10 {
public static void main(String[] args) throws Exception{
//不使用反射机制
//创建对象
UserService userService = new UserService();
//调用方法
/*
要素分析:
1.对象:userService
2.方法名:login
3.实参列表:"admin","123"
4.返回值:loginSuccess
*/
boolean loginSuccess = userService.login("admin","123");
System.out.println(loginSuccess?"登录成功" : "登录失败");//登录成功
//使用反射机制调用一个对象的方法
Class userServiceClass = Class.forName("service.UserService");
//创建对象
Object obj = userServiceClass.newInstance();
//获取Method
Method loginMethod = userServiceClass.getDeclaredMethod("login", String.class, String.class);
//调用方法 也需要四要素
/*
要素分析:
1.对象:obj
2.方法名:loginMethod
3.实参列表:"admin","123"
4.返回值:retValue
*/
//反射机制中最重要的一个方法
Object retValue = loginMethod.invoke(obj,"admin","123");
System.out.println(retValue);//true
}
}
8.反射Constructor
Vip类:
package bean;
public class Vip {
int no;
String name;
String birth;
boolean sex;
public Vip() {
}
public Vip(int no) {
this.no = no;
}
public Vip(int no, String name) {
this.no = no;
this.name = name;
}
public Vip(int no, String name, String birth) {
this.no = no;
this.name = name;
this.birth = birth;
}
public Vip(int no, String name, String birth, boolean sex) {
this.no = no;
this.name = name;
this.birth = birth;
this.sex = sex;
}
}
测试类:
package Reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class ReflectTest11 {
public static void main(String[] args) throws Exception{
StringBuilder s = new StringBuilder();
Class vipClass = Class.forName("bean.Vip");
s.append(Modifier.toString(vipClass.getModifiers()));
s.append(" class ");
s.append(vipClass.getSimpleName());
s.append("{\n");
//拼接构造方法
Constructor[] constructors = vipClass.getDeclaredConstructors();
for (Constructor constructor : constructors){
//public Vip(int no, String name, String birth, boolean sex) {}
s.append("\t");
s.append(Modifier.toString(constructor.getModifiers()));
s.append(" ");
s.append(vipClass.getSimpleName());
s.append("(");
//拼接参数
Class[] parameterTypes = constructor.getParameterTypes();
for (Class parameterType : parameterTypes){
s.append(parameterType.getSimpleName());
s.append(",");
}
//删除最后下标位置上的字符
if (parameterTypes.length > 0){
s.deleteCharAt(s.length() - 1);
}
s.append("){}\n");
}
s.append("}");
System.out.println(s);
}
}
运行结果:
9.反射机制调用构造方法
Vip类:
package bean;
public class Vip {
int no;
String name;
String birth;
boolean sex;
public Vip() {
}
public Vip(int no) {
this.no = no;
}
public Vip(int no, String name) {
this.no = no;
this.name = name;
}
public Vip(int no, String name, String birth) {
this.no = no;
this.name = name;
this.birth = birth;
}
public Vip(int no, String name, String birth, boolean sex) {
this.no = no;
this.name = name;
this.birth = birth;
this.sex = sex;
}
@Override
public String toString() {
return "Vip{" +
"no=" + no +
", name='" + name + '\'' +
", birth='" + birth + '\'' +
", sex=" + sex +
'}';
}
}
测试类:
package Reflect;
import bean.Vip;
import java.lang.reflect.Constructor;
public class ReflectTest12 {
public static void main(String[] args) throws Exception {
//不使用反射机制创建对象
Vip v1 = new Vip();
Vip v2 = new Vip(110,"zhangsan","2022-04-06",true);
//使用反射机制创建对象
Class c = Class.forName("bean.Vip");
//调用无参数构造方法
Object obj = c.newInstance();
System.out.println(obj);
//调用有参数的构造方法
//第一步:先获取到这个有参数的构造方法
Constructor con = c.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
//第二步:调用构造方法new对象
Object newObj = con.newInstance(110,"jackson","1990-10-11",true);
System.out.println(newObj);
//获取无参数构造方法
Constructor con2 = c.getDeclaredConstructor() ;
Object newObj2 = con2.newInstance();
System.out.println(newObj2);
}
}
运行结果:
10.获取父类和父类接口
获取一个类的父类以及实现的接口
package Reflect;
public class ReflectTest13 {
public static void main(String[] args) throws Exception{
//String举例
Class stringClass = Class.forName("java.lang.String");
//获取String的父类
Class superClass = stringClass.getSuperclass();
System.out.println(superClass.getName());
//获取String类实现的所有接口(一个类可以实现多个接口)
Class[] interfaces = stringClass.getInterfaces();
for (Class in :interfaces){
System.out.println(in.getName());
}
}
}
运行结果: