反射

什么是反射

反射(Reflection) 是一种在运行时(Runtime) 动态分析、检查和操作类、方法、字段、构造方法等程序结构的能力。

通俗来说,通过Java中的反射机制,可以程序运行期间,在不知道具体类或者对象的情况下,通过该类的字节码对象,动态加载类、创建对象、调用方法、访问字段,甚至是修改私有成员。

反射提供了一种全新的创建对象,调用方法,访问成员变量的形式。

反射的起点是字节码对象。

获取字节码文件对象的几种方式

  • 对象.getClass()
  • 类名.class
  • Class.forName(String className) 全限定名
  • ClassLoader里的loadClass(String className)

注意:

无论通过什么方式获取的字节码文件对象 都是同一个

Demo

package _23reflect.com.cskaoyan._02cls;

/*
获取字节码文件对象的几种方式
*/
public class Demo {
   public static void main(String[] args) throws ClassNotFoundException {
       // 对象.getClass
       A a = new A();
       Class<? extends A> c1 = a.getClass();

       // 类名.class
       Class<A> c2 = A.class;

       System.out.println(c1 == c2);

       // Class.forName(全限定名)
       Class<?> c3 = Class.forName("_23reflect.com.cskaoyan._02cls.A");

       System.out.println(c1 == c3);

       // ClassLoader.loadClass(String className)
       ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
       Class<?> c4 = systemClassLoader.loadClass("_23reflect.com.cskaoyan._02cls.A");
       System.out.println(c1 == c4);

  }
}

class A{

}

关于Class

Class 类的实例表示正在运行的 Java 应用程序中的类和接口

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

通过反射获取构造方法(Constructor)

通过反射获取所有构造方法

// 获取所有的public修饰的构造方法
Constructor[] getConstructors()
   
   
// 获取所有的构造方法,包括私有构造方法
Constructor[] getDeclaredConstructors()

获取指定构造方法

Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

使用Constructor创建对象

Person p = new Person("zs",20,true)
newInstance(参数列表)

暴力破解

setAccessible(true) 
package _23reflect.com.cskaoyan._04api;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;



public class ConstructorTest {
   public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
       // 反射技术的起点 获取字节码文件对象
       Class<?> stuCls = Class.forName("_23reflect.com.cskaoyan.bean.Person");

       System.out.println("获取所有的public的构造方法----");
       // Constructor[] getConstructors()
       Constructor<?>[] constructors = stuCls.getConstructors();
       for (Constructor<?> constructor : constructors) {
           System.out.println(constructor);
      }

       System.out.println("获取所有的构造方法----");

       //Constructor[] getDeclaredConstructors()
       Constructor<?>[] declaredConstructors = stuCls.getDeclaredConstructors();
       for (Constructor<?> constructor : declaredConstructors) {
           System.out.println(constructor);
      }
       System.out.println("获取指定的public的构造方法----");
       // Constructor<T> getConstructor(Class<?>... parameterTypes)
       Constructor<?> constructor = stuCls.getConstructor(String.class, int.class, boolean.class);
       //Constructor<?> constructor = stuCls.getConstructor(String.class, int.class);
       // java.lang.NoSuchMethodException


       System.out.println(constructor);
       System.out.println("获取指定的构造方法----");
       //Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
       Constructor<?> declaredConstructor = stuCls.getDeclaredConstructor(String.class, int.class);
       System.out.println(declaredConstructor);

       // 使用构造方法对象创建对象
       // newInstance
       Object o = constructor.newInstance("zs", 20, true);
       System.out.println(o);

       // java.lang.IllegalAccessException
       // setAccessible(true) 忽略java语法检查
       declaredConstructor.setAccessible(true);
       Object o1 = declaredConstructor.newInstance("ls", 21);
       System.out.println(o1);


  }
}

通过反射获取成员变量(Field)

通过反射获取所有成员变量

// 获取所有public 修饰的成员变量,包括继承自父类中的成员
Field[] getFields()
   
// 获取所有在该类中定义的成员,包括私有成员    
Field[] getDeclaredFields()

获取指定成员变量

Field getField(String name)
Field getDeclaredField(String name)

通过Field读写对象的成员变量(可暴力破解)

Object get(Object obj):获取值,传入对象
void set(Object obj, Object value):赋值,传入对象
package _23reflect.com.cskaoyan._04api;

import _23reflect.com.cskaoyan.bean.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/*
反射获取成员变量

*/
public class FieldTest {
   public static void main(String[] args) throws Exception{
       // 获取字节码文件对象
       Class<?> personCls = Class.forName("_23reflect.com.cskaoyan.bean.Person");
       System.out.println("获取所有的public的成员变量------");
       // Field[] getFields()
       Field[] fields = personCls.getFields();
       for (Field field : fields) {
           System.out.println(field);
      }
       System.out.println("获取所有的成员变量------");

       //Field[] getDeclaredFields()
       Field[] declaredFields = personCls.getDeclaredFields();
       for (Field field : declaredFields) {
           System.out.println(field);
      }
       System.out.println("获取指定的public的成员变量------");
       // Field getField(String name)
       Field nameField = personCls.getField("name");
       System.out.println(nameField);
       System.out.println("获取指定的成员变量------");

       //Field getDeclaredField(String name)
       Field ageField = personCls.getDeclaredField("age");
       System.out.println(ageField);

       // 给成员变量赋值 获取成员变量的值
       //void set(Object obj, Object value):赋值,传入对象
       Constructor<?> declaredConstructor = personCls.getDeclaredConstructor();
       // 实例化对象
       Object o = declaredConstructor.newInstance();
       nameField.set(o, "zs");
       System.out.println(o);

       ageField.setAccessible(true);
       ageField.set(o, 22);
       System.out.println(o);
       // Object get(Object obj):获取值,传入对象
       Object o1 = nameField.get(o);
       System.out.println(o1);
  }
}

通过反射获取成员方法(Method)

获取所有成员方法

// 获取所有的public修饰的方法,包括继承的父类中的方法
Method[] getMethods();

// 获取所有在该类中定义的方法,包括私有方法,不包括父类中的方法
Method[] getDeclaredMethods()

获取指定的成员方法

Method getMethod(String name, Class<?>... parameterTypes)
Method getDeclaredMethod(String name, Class<?>... parameterTypes)

利用Method调用对象的方法

Object invoke(Object obj, Object... args)
package _23reflect.com.cskaoyan._04api;

import _23reflect.com.cskaoyan.bean.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
* @description:
* @author: 景天
* @date: 2022/10/24 14:39
**/
/*
通过反射获取方法
*/
public class MethodTest {
   public static void main(String[] args) throws Exception{
       // 获取字节码文件对象
       Class<?> personCls = Class.forName("_23reflect.com.cskaoyan.bean.Person");

       System.out.println("获取所有的public的方法----");
       // Method[] getMethods()
       Method[] methods = personCls.getMethods();
       for (Method method : methods) {
           System.out.println(method);
      }
       System.out.println("获取所有的方法----");

       //Method[] getDeclaredMethods()
       Method[] declaredMethods = personCls.getDeclaredMethods();
       for (Method method : declaredMethods) {
           System.out.println(method);
      }

       System.out.println("获取指定的public的方法----");
       // Method getMethod(String name, Class<?>... parameterTypes)
       Method eatMethod1 = personCls.getMethod("eat");
       System.out.println(eatMethod1);

       System.out.println("获取指定的方法----");

       //Method getDeclaredMethod(String name, Class<?>... parameterTypes)
       Method eatMethod2 = personCls.getDeclaredMethod("eat", String.class);
       System.out.println(eatMethod2);

       //Person p = new Person();
       //p.eat();

       // 反射调用方法
       // Object invoke(Object obj, Object... args)
       Constructor<?> declaredConstructor = personCls.getDeclaredConstructor();
       Object o = declaredConstructor.newInstance();
       Object invoke = eatMethod1.invoke(o);
       System.out.println(invoke);

       eatMethod2.setAccessible(true);
       eatMethod2.invoke(o, "apple");

  }
}

补充

其他API

package _23reflect.com.cskaoyan.bean;

/**
* @description:
* @author: 景天
* @date: 2022/10/24 11:31
**/

public class Person {
   // 定义成员变量
   public  String name;
   private int age;
   boolean gender;

   // 构造方法

   public Person(String name, int age, boolean gender) {
       this.name = name;
       this.age = age;
       this.gender = gender;
  }

   private Person(String name, int age) {
       this.name = name;
       this.age = age;
  }

   public Person() {
  }

   // 定义成员方法

   @Override
   public String toString() {
       return "Person{" +
               "name='" + name + '\'' +
               ", age=" + age +
               ", gender=" + gender +
               '}';
  }

   public String eat(){
       System.out.println("eat food!");
       return "吃了";
  }

   private void eat(String food){
       System.out.println("eat " + food);
  }
}


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;


public class OtherApi {
   public static void main(String[] args) throws Exception{
       // 获取字节码文件对象
       Class<?> c = Class.forName("_23reflect.com.cskaoyan.bean.Person");
       //Class<?> c = Class.forName("java.io.OutputStream");
       // 获取全限定类名
       System.out.println(c.getName());
       // 获取简单名称
       System.out.println("c.getSimpleName() = " + c.getSimpleName());
       // 获取父类
       Class<?> superclass = c.getSuperclass();
       System.out.println("superclass = " + superclass.getSimpleName());

       // 获取实现的接口
       Class<?>[] interfaces = c.getInterfaces();
       for (Class<?> i : interfaces) {
           System.out.println(i);
      }
       // 获取类加载器
       ClassLoader classLoader = c.getClassLoader();
       System.out.println("classLoader = " + classLoader);

       // 获取name这个成员变量对象
       Field nameField = c.getDeclaredField("name");
       // 获取权限修饰符
       int modifiers = nameField.getModifiers();
       System.out.println(modifiers);
       // static String toString(int mod)
       // 返回描述指定修饰符中的访问修饰符标志的字符串。
       String s = Modifier.toString(modifiers);
       System.out.println("s = " + s);

       // 获取eat(String s)方法对象
       Method eatMethod = c.getDeclaredMethod("eat", String.class);
       Class<?> returnType = eatMethod.getReturnType();
       System.out.println("returnType = " + returnType);
       Class<?>[] parameterTypes = eatMethod.getParameterTypes();
       for (Class<?> parameterType : parameterTypes) {
           System.out.println(parameterType.getSimpleName());
      }
  }
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇