반사 메커니즘은 실행 상태에 있으며 Java에 "객체 작동" 기능을 제공합니다. 실행 상태에서는 클래스 파일 객체를 통해 프라이빗을 포함한 모든 클래스의 속성, 메서드 및 생성자를 호출할 수 있습니다. 예, 모든 클래스는 리플렉션 메커니즘 앞에서 투명합니다
나만의 요약: 클래스 파일 객체를 통해 이 클래스의 모든 것을 볼 수 있으며 이를 사용하고 수정할 수 있습니다
리플렉션의 전제는 다음을 얻는 것입니다. 클래스 파일 Object((바이트코드 객체)를 얻는 방법에는 세 가지가 있습니다:
Class.forName ("전체 클래스 이름") ---- Class 클래스의 정적 메서드를 통해(가장 일반적으로 사용됨)
class Name.class
Object.getClass()
//方式1:获取字节码对象,Class.forName("全类名") Class cla1 = Class.forName("Study01.Person"); //方式2: 类名.Class Class cla2 = Person.class; //方式3:对象.getClass(); Person per = new Person(); Class cla3 = per.getClass(); //这三个class对象都是由Person这个类生成的 //那么我们看一下这三个字节码对象是不是同一个: System.out.println(cla1==cla2); System.out.println(cla2==cla3);
//출력 결과: 두 개의 true
결론:
바이트코드 객체는 클래스가 로드될 때 생성되며,
바이트코드 객체를 얻는 방법은 무엇이든 상관없이 동일한 바이트코드 객체입니다
리플렉션을 통해 클래스의 속성을 가져옵니다.
클래스 바이트코드 객체를 얻은 후 다음을 사용할 수 있습니다.
클래스 메소드의 일부:
1. 두 개의 공개 속성과 두 개의 비공개 속성(구성 및 가져오기/설정을 설정하지 않고 리플렉션이 내부 값을 얻을 수 있는지 확인하세요)
public class Person { private String name; //名字 private int age = 18; //年龄 public int ID = 123; //身份证 public String Sex; //性别 @Override public String toString(){ return "姓名"+name+"年龄:"+age+"ID:"+ID+"性别:"+Sex; } }
테스트 클래스:
public class Test { public static void main(String[] args) throws ClassNotFoundException { //获取Class文件对象,用最常用的通过Class类的静态方法 Class per = Class.forName("Test01.Person"); //这里是传入全路径!!从最外层的包名开始! //使用getFields()方法获取全部被public修饰的属性(方法上面的截图有) //并且返回的是Field类型的数组 Field fields[] = per.getFields(); for (Field field:fields) { System.out.println(field); } } }
출력:
우리는 모든 Person 클래스 공개 속성을 성공적으로 얻었습니다.
2 비공개 속성을 포함한 모든 속성을 가져올 수도 있습니다. (다른 코드는 다시 작성되지 않습니다.)
for (Field field : per.getDeclaredFields()) { System.out.println(field); }
출력:
3 공개 속성을 가져오고 값을 수정합니다.
Field f = per.getField("Sex"); System.out.println(f); //获取一个对象: Object obj = per.getConstructor().newInstance(); //修改值: f.set(obj,"男"); Person p = (Person)obj; System.out.println(p.Sex);
출력:
4. private 속성을 가져오고 값을 수정합니다. 여기에 위에서 수정한 public 속성의 값도 연결합니다.
Person p = (Person)obj; //获取公有字段并调用,并修改 Field f = per.getField("Sex"); //获取一个对象: Object obj = per.getConstructor().newInstance(); f.set(obj,"男"); //将Sex的属性修改成了 男 //调用私有的属性,并修改 f = per.getDeclaredField("name"); //在访问私有的属性的值之前,先要设置运行访问↓ //在访问之前忽略访问权限的检查,叫暴力反射 f.setAccessible(true); f.set(obj,"张三"); System.out.println("Person里面的信息是:"+p.toString()); } }
출력:
리플렉션을 통해 클래스 가져오기 방법(public, private) , 생성자):
Person 클래스:
public class Person { private String name; //名字 private int age = 18; //年龄 public int ID = 123; //身份证 public String Sex ; //性别 //构造: public Person() {} public Person(String name, int age, int ID, String sex) { this.name = name; this.age = age; this.ID = ID; Sex = sex; } //无参公有方法: public void eat(){ System.out.println("我会吃饭"); } //有参公有方法: public void eat(String food){ System.out.println("我在吃:"+food); } //有参私有方法 private void play(String name){ System.out.println(name+"在玩"); } }
Test 클래스:
public class Test { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { //获取到Person以及父类Object里面的public方法: System.out.println("-----获取到Person以及父类Object里面的public方法↓-----"); for (Method method : Person.class.getMethods()) { System.out.println(method); System.out.println("方法名:"+ method.getName()); } //获取到Person里面的方法,包括私有 System.out.println("-----获取到Person里面的方法,包括私有↓-----"); for (Method method:Person.class.getDeclaredMethods()) { System.out.println(method.getName()+" "); } //按照方法名获取到Person中的eat方法: System.out.println("-----根据方法名获取到Person类中的eat方法↓-----"); Method earMethod1 = Person.class.getMethod("eat"); Person per = new Person(); //通过invoke(Object,param...)来调用指定的方法 earMethod1.invoke(per); //使用反射调用有参方法; System.out.println("-----使用反射调用有参方法(传入参数)↓-----"); Method earMethod2 = Person.class.getMethod("eat",String.class); earMethod2.invoke(per,"牛肉"); //通过暴力反射获取到私有的play方法: System.out.println("-----通过暴力反射获取到私有的play方法传入参数)↓-----"); Method earMethod3 = Person.class.getDeclaredMethod("play", String.class); //在访问私有的属性的方法之前,先要设置运行访问 earMethod3.setAccessible(true); earMethod3.invoke(per,"小王"); }
Output:
------Person 및 상위 클래스 Object에서 공용 메소드 가져오기↓--- --
public void Test02.Person .eat(java.lang.String)
메서드 이름: eat
public void Test02.Person.eat()
메서드 이름: eat
public final void java.lang.Object.wait()에서 java.lang.InterruptedException
Method가 발생합니다. 이름: wait
public final void java.lang.Object.wait(long,int)는 java.lang.InterruptedException
메소드 이름: wait
public final 기본 void java.lang.Object.wait(long)은 java.lang을 발생시킵니다. InterruptedException
메서드 이름: wait
public boolean java.lang.Object.equals(java.lang.Object)
메서드 이름: equals
public java.lang.String java.lang.Object.toString ()
메서드 이름: toString
public Native int java.lang.Object.hashCode()
메서드 이름: hashCode
public final Native java.lang.Class java.lang.Object.getClass()
메서드 이름: getClass
public final Native void java.lang.Object .notify()
메서드 이름: inform
public final Native void java.lang.Object.notifyAll()
메서드 이름: informAll
위 내용은 Java 반사 메커니즘 원리 분석 예시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!