码迷,mamicode.com
首页 > 编程语言 > 详细

Java反射机制

时间:2019-02-20 20:07:16      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:语言   otf   china   print   ref   struct   耦合   类加载器   判断   

Java让我们在识别对象和类的信息,主要有两种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息;另一种是反射机制,它允许我们在运行时发现和使用类的信息。

使用反射赋予了Java动态编译的能力,否则类的元数据信息只能通过静态编译的方式实现。

Java中编译类型有两种:

静态编译:在编译时确定类型,绑定对象即通过

动态编译:运行时确定类型,绑定对象。动态编译最大限度地发挥了Java的灵活性,体现了多态的应用,可以降低类之间的耦合性。

什么是反射?

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

Java Reflection

  反射是被视为动态语言的关键,反射机制允许程序在执行期间借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法。

Java反射机制提供的功能

  在运行时判断任意一个对象所属的类

  在运行的时候构造任意一个类的对象

  在运行时判断任意一个类所具有的成员变量和方法

  在运行时调用任意一个对象的成员变量和方法

 


public class Person {
public String name;
private int age;
public int id;

public Person() {

}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}

public void show(){
System.out.println("我是人类");
}

public void display(String nation){
System.out.println("我的家乡:"+nation);
}

public static void info(){
System.out.println("元宵节快乐!");
}

}

 

 

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

import org.junit.Test;

public class TestField {

// 获取对应运行时类的属性
@Test
public void test1(){
Class clazz = Person.class;
// 1.getFields():只能获取运行时类中及其父类声明为public的属性
Field[] fields = clazz.getFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i].getName());
}

//2.getDeclaredFields():获取运行时类本身声明的所有属性
Field[] fields2 = clazz.getDeclaredFields();
for (Field f : fields2) {
System.out.println(f.getName());
}
}

// 获取权限修饰符 变量类型 属性名
@Test
public void test2(){
Class clazz = Person.class;
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
// 1.获取每个属性的访问修饰符
int i = f.getModifiers();
System.out.println(Modifier.toString(i)+" ");
// 2.获取属性的类型
Class type = f.getType();
System.out.println(type.getName()+" ");
// 3.获取属性名
System.out.println(f.getName()+" ");
System.out.println();
}
}

// 调用运行时类中指定的属性
@Test
public void test3() throws Exception{
Class clazz = Person.class;
// 1.获取指定的属性
// getField(String fieldName):获取运行时类中声明为public的属性名
Field name = clazz.getField("name");
// 2.创建运行时类的对象
Person p = (Person) clazz.newInstance();
System.out.println(p);
// 3.将运行时类的属性赋值
name.set(p, "jack");
System.out.println(p);
// 4.getDeclaredField(String fieldName):获取运行时类中指定的名为fieldName的属性
Field age = clazz.getDeclaredField("age");
// 由于属性权限修饰符的限制,为了保证可以为属性赋值,需要在操作前使得此属性可以被操作。
age.setAccessible(true);
age.set(p, 20);
System.out.println(p);
}
}

 

 

import java.lang.reflect.Constructor;

import org.junit.Test;

public class TestConstructor {
@Test
public void test1() throws Exception{
// 创建对应运行时类的对象使用newInstance()实际上是调用了运行时类的空参构造器
// 要求:1.对应的运行时类要有空参的构造器 2.构造器的权限修饰符权限要足够
String className = "com.hpe.reflect.Person";
Class clazz = Class.forName(className);
Person p = (Person) clazz.newInstance();
System.out.println(p);
}

// 获取Person类中所有的构造器
@Test
public void test2() throws Exception{
Class clazz = Class.forName("com.hpe.reflect.Person");
Constructor[] cons = clazz.getDeclaredConstructors();
for (Constructor c : cons) {
System.out.println(c);
}
}

// 调用指定的构造器
@Test
public void test3() throws Exception{
Class clazz = Class.forName("com.hpe.reflect.Person");
Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Person p = (Person) cons.newInstance("张三",20);
System.out.println(p);
}
}

 

 

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

import org.junit.Test;

public class TestMethod {

// 调用运行时类中指定的方法
@Test
public void test1() throws Exception{
Class clazz = Person.class;
// getMethod(String methodName,class... params):获取运行时类中声明为public的方法
Method m1 = clazz.getMethod("show");
Person p = (Person) clazz.newInstance();
// 调用指定的方法Object invoke(Object obj,Object... obj)
Object returnVal = m1.invoke(p);
System.out.println(returnVal);

// 带有返回值类型的方法
Method m2 = clazz.getMethod("toString");

// 设置属性值
Field name = clazz.getField("name");
name.set(p, "lim");
Object returnVal2 = m2.invoke(p);
System.out.println(returnVal2);

// 调用静态方法
Method m3 = clazz.getMethod("info");
m3.invoke(Person.class);
// getDeclaredMethod(String methodName,class...param):获取运行时类声明的指定方法
Method m4 = clazz.getDeclaredMethod("display", String.class);
m4.setAccessible(true);
m4.invoke(p, "CHN");
}
}

 


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

import org.junit.Test;

public class TestReflection {

// 通过传统方式调用对象 调用其方法
@Test
public void test1(){
Person p = new Person();
p.setAge(15);
p.setName("jack");
System.out.println(p);
p.show();
p.display("山东");
}

// 有了反射,可以通过反射创建一个类的对象,并调用其中的结构
@Test
public void test2() throws Exception{
Class clazz = Person.class;
// 1.创建clazz对应运行时类Person类的对象
Person p = (Person)clazz.newInstance();
System.out.println(p);
// 2、通过反射调用运行时类指定的属性
Field f1 = clazz.getField("name");
// 设置某个对象的属性值
f1.set(p, "jack");
System.out.println(p);

Field f2 = clazz.getDeclaredField("age");
// 设置允许访问
f2.setAccessible(true);
f2.set(p, 20);
System.out.println(p);
// 3.通过反射调用运行时类指定的方法
Method m1 = clazz.getMethod("show");
// 调用方法
m1.invoke(p);

Method m2 = clazz.getMethod("display", String.class);
m2.invoke(p, "China");
}

/*
* java.lang.Class:反射的源
* 创建一个类,通过编译(javac.exe)生成对应的class文件,之后我们通过java.exe(JVM类加载器)加载此class文件
* 到内存,就是一个运行时类,存放在缓存区。Class clazz = Person.class
* 1.每个运行时类只加载一次
* 2.有了Class实例后,可以执行:
* ①.创建对应运行时类的对象(重点)
* ②.获取对应运行时类的完整结构(属性、方法、构造器、内部类、父类、包、异常、注解)
* ③.调用对应的运行时类的指定结构(属性、方法、构造器)(重点)
*/
@Test
public void test3(){
Person p = new Person();
// 调用其getClass()方法返回运行时类
Class clazz = p.getClass();// Person.class
System.out.println(clazz);
}

@Test
public void test4() throws ClassNotFoundException{
// 1.调用类本身的.class属性
Class clazz1 = Person.class;
System.out.println(clazz1.getName());

Class clazz2 = String.class;
System.out.println(clazz2.getName());

// 2.通过类的对象获取
Person p = new Person();
Class clazz3 = p.getClass();
System.out.println(clazz3.getName());

// 3.通过Class类的静态方法获取
String className = "com.hpe.reflect.Person";
Class clazz4 = Class.forName(className);
System.out.println(clazz4.getName());

// 4.通过类的加载器(了解)
ClassLoader classLoader = this.getClass().getClassLoader();
Class clazz5 = classLoader.loadClass(className);
System.out.println(clazz5.getName());
}
}

Java反射机制

标签:语言   otf   china   print   ref   struct   耦合   类加载器   判断   

原文地址:https://www.cnblogs.com/qust-lgh/p/10408597.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!