JavaSE复习总结之反射机制

x33g5p2x  于2022-03-31 转载在 Java  
字(6.0k)|赞(0)|评价(0)|浏览(228)

反射的概念

反射的概念是由 Smith 在 1982 年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力, 并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

反射的工作机制

程序运行时,Java系统会一直对所有对象进行所谓的运行时类型识别,这项信息记录了每个对象所属的类。通过专门的类可以访问这些信息。用来保存这些信息的类是class 类,通过Java语言中的反射机制可以操作字节码文件

获取Class的三种方式

  • 第一种:Class c = Class.forName(“完整类名”);
  • 第二种:Class c = 对象.getClass();
  • 第三种:Class c = 任何类型.class;

获取到Class能干什么

一、实例化对象

//不使用反射机制创建对象
	User user = new User();
	System.out.println(user);
	//使用反射机制创建对象
	try {
		// 通过反射机制,获取Class,通过Class来实例化对象
		Class c = Class.forName("com.bjpowernode.java.bean.User");
		// newInstance()调用的是无参构造,必须保证无参构造是存在的!
		Object obj = c.newInstance();
		System.out.println(obj);
	} catch (Exception e) {
		e.printStackTrace();
	}

二、获取类的属性

返回类型方法名描述
StringgetName()获取完整类名
StringgetSimpleName()获取简类名
Field[]getFields()获取类中所有的public修饰的属性
Field[]getDeclaredFields()获取类中所有的属性
FieldgetDeclaredField(String name)根据属性名获取属性

Filed类常用方法

返回类型方法名描述
StringgetName()获取属性名
intgetModifiers()返回的修饰符是一个数字(修饰符的代号)
ClassgetType()获取属性的类型
public class ReflectTest {
    public static void main(String[] args) throws Exception{
        Class studentClass = Class.forName("com.why.java.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);
        // 取出这个Field
        Field f = fields[0];
        // 取出这个Field它的名字
        String fieldName = f.getName();
        System.out.println(fieldName);
        // 获取所有的Field
        Field[] fs = studentClass.getDeclaredFields();
        // 遍历
        for(Field field : fs){
            // 获取属性的修饰符列表
            int i = field.getModifiers(); 
            // 将这个“代号”数字转换成“字符串”吗
            String modifierString = Modifier.toString(i);
            System.out.print(modifierString+" ");
            // 获取属性的类型
            Class fieldType = field.getType();
            String fName = fieldType.getSimpleName();
            System.out.print(fName+" ");
            // 获取属性的名字
            System.out.println(field.getName());
        }
    }
}

【运行结果】

完整类名:com.why.java.bean.Student
简类名:Student
private String name
protected int age
 boolean sex
public int no
public static final double MATH_PI

Process finished with exit code 0

三、访问对象属性

给属性赋值set
获取属性的值get

public class ReflectTest {
    public static void main(String[] args) throws Exception{

        // 不使用反射机制访问一个对象的属性
        Student s = new Student();
        s.no = 1111;
        System.out.println(s.no);

        // 使用反射机制访问一个对象的属性
        Class studentClass = Class.forName("com.why.java.bean.Student");
        Object obj = studentClass.newInstance(); 
        // 获取no属性(根据属性的名称来获取Field)
        Field noFiled = studentClass.getDeclaredField("no");
        // 给obj对象(Student对象)的no属性赋值
        noFiled.set(obj, 22222); // 给obj对象的no属性赋值2222
        // 读取属性的值
        System.out.println(noFiled.get(obj));
        Field nameField = studentClass.getDeclaredField("name");
        // 这样设置完之后,在外部也是可以访问private的。
        nameField.setAccessible(true);
        // 给name属性赋值
        nameField.set(obj, "jackson");
        // 获取name属性的值
        System.out.println(nameField.get(obj));
    }
}

四、获取类的方法

返回类型方法名描述
Method[]getDeclaredMethods()获取所有的方法包括私有
MethodgetMethod(String name, Class<?>… parameterTypes)根据方法名和形参获取方法
Class[]getParameterTypes()获取形参类型
Constructor[]getDeclaredConstructors()获取所有的构造方法
public class ReflectTest {
    public static void main(String[] args) throws Exception{
        Class userServiceClass = Class.forName("com.why.java.service.UserService");
        Method[] methods = userServiceClass.getDeclaredMethods();
        // 遍历Method
        for(Method method : methods){
            // 获取修饰符列表
            System.out.print(Modifier.toString(method.getModifiers())+" ");
            // 获取方法的返回值类型
            System.out.print(method.getReturnType().getSimpleName()+" ");
            // 获取方法名
            System.out.print(method.getName()+"(");
            // 方法的修饰符列表(一个方法的参数可能会有多个。)
            Class[] parameterTypes = method.getParameterTypes();
            for(Class parameterType : parameterTypes){
                System.out.print(parameterType.getSimpleName()+",");
            }
            System.out.println(")");
        }
    }
}

【运行结果】

public void login(int,)
public boolean login(String,String,)
public void logout()

Process finished with exit code 0

五、调用对象方法

public class ReflectTest10 {
    public static void main(String[] args) throws Exception{
        // 不使用反射机制调用方法
        UserService userService = new UserService();
        boolean loginSuccess = userService.login("admin","123");
        System.out.println(loginSuccess ? "登录成功" : "登录失败");

        // 使用反射机制来调用一个对象的方法
        Class userServiceClass = Class.forName("com.why.java.service.UserService");
        Object obj = userServiceClass.newInstance();
        // 获取Method
        Method loginMethod = userServiceClass.getDeclaredMethod("login", String.class, String.class);
        Object retValue = loginMethod.invoke(obj, "admin","123123");
        System.out.println(retValue);
    }
}

六、通过反射机制调用构造方法实例化java对象

public class ReflectTest12 {
    public static void main(String[] args) throws Exception{
        // 使用反射机制怎么创建对象
        Class c = Class.forName("com.bjpowernode.java.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);
    }
}

七、获取父类和实现的接口

返回类型方法名描述
ClassgetSuperclass()获取父类
Class[]getInterfaces()获取实现的所有接口
public class ReflectTest13 {
    public static void main(String[] args) throws Exception{
        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());
        }
    }
}

【运行结果】

java.lang.Object
java.io.Serializable
java.lang.Comparable
java.lang.CharSequence
java.lang.constant.Constable
java.lang.constant.ConstantDesc

Process finished with exit code 0

资源绑定器

java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容。使用以下这种方式的时候,属性配置文件xxx.properties必须放到类路径下。

properties文件

className=java.lang.String
public class ResourceBundleTest {
    public static void main(String[] args) {

        // 这个文件必须在类路径下。文件扩展名也必须是properties
        // 并且在写路径的时候,路径后面的扩展名不能写
        //ResourceBundle bundle = ResourceBundle.getBundle("db");

        ResourceBundle bundle = ResourceBundle.getBundle("com/why/java/bean/db");
        String className = bundle.getString("className");
        System.out.println(className);
    }
}

【结果】

java.lang.String

Process finished with exit code 0

相关文章