龙空技术网

java反射机制详解

程序员COW哥 238

前言:

当前同学们对“python反射”大概比较注重,朋友们都需要知道一些“python反射”的相关内容。那么小编同时在网摘上收集了一些关于“python反射””的相关知识,希望兄弟们能喜欢,你们一起来学习一下吧!

一 , 什么是java反射机制?

JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methodsJava 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”JAVA反射提供的功能在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象在运行时判断任意一个类所具有的成员变量和方法在运行时调用任意一个对象的方法

在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:

Class类:代表一个类

Field 类:代表类的成员变量(成员变量也称为类的属性)

Method类:代表类的方法

Constructor 类:代表类的构造方法

Array类:提供了动态创建数组,以及访问数组的元素的静态方法

Reflection API的实际运用

在java.lang.Object 类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API 中的核心类,它有以下方法

getName():获得类的完整名字。

getFields():获得类的public类型的属性。

getDeclaredFields():获得类的所有属性。

getMethods():获得类的public类型的方法。

getDeclaredMethods():获得类的所有方法。

getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。

getConstructors():获得类的public类型的构造方法。

getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。

newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

利用反射机制运行时复制对象

public class User {

private Long id;

private String name;

private int age;

public User() {

}

public Customer(final String name, final int age) {

this.name = name;

this.age = age;

}

public Long getId() {

return id;

}

public void setId(final Long id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName (final String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(final int age) {

this.age = age;

}

}

ublic class ReflectTest {

public Object copy(final Object object) throws Exception {

Class<?> classType = object.getClass(); // 获得对象的类型

System.out.println("Class:" + classType.getName());

// 通过默认构造方法创建一个新的对象

Object objectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});

Field fields[] = classType.getDeclaredFields(); // 获得对象的所有属性

for (int i = 0; i < fields.length; i++) {

Field field = fields[i];

String fieldName = field.getName();

String firstLetter = fieldName.substring(0, 1).toUpperCase();

String getMethodName = "get" + firstLetter + fieldName.substring(1); // 获得和属性对应的getXXX()方法的名字

String setMethodName = "set" + firstLetter + fieldName.substring(1); // 获得和属性对应的setXXX()方法的名字

// 获得和属性对应的getXXX()方法

Method getMethod = classType.getMethod(getMethodName, new Class[]{});

// 获得和属性对应的setXXX()方法

Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()});

Object value = getMethod.invoke(object, new Object[]{}); // 调用原对象的getXXX()方法

System.out.println(fieldName + ":" + value);

setMethod.invoke(objectCopy, new Object[]{value}); // 调用拷贝对象的setXXX()方法

}

return objectCopy;

}

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

User user= new User("Tom", 21);

user.setId(new Long(1));

User userCopy = (User) new ReflectTest().copy(customer);

System.out.println("Copy information:" + userCopy.getId() + " " + userCopy.getName() + " "

+ userCopy.getAge());

}

}

动态创建和访问数组元素的各种静态方法。

例程ArrayTest 类的main()方法创建了一个长度为15 的字符串数组,接着把索引位置为11 的元素设为“hello word”,然后再读取索引位置为10 的元素的值

public class ArrayTester1 {

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

Class<?> classType = Class.forName("java.lang.String");

Object myArray = Array.newInstance(classType, 15); // 创建一个长度为15的字符串数组

Array.set(myArray, 10, "hello word"); // 把索引位置为10的元素设为"hello"

String s = (String) Array.get(array, 10); // 获得索引位置为10的元素的值

System.out.println(s);

}

}

main()方法创建了一个 10 x 20 x 30 的整型数组,并把索引位置为[4][10][20] 的元素的值为设50。

public class ArrayTest {

public static void main(String args[]) {

int[] dimArray = new int[]{10, 20, 30};

Object array = Array.newInstance(Integer.TYPE, dimArray);//创建一个具有指定的数值类型和三个维度的新数组。

final Object arrayObjecy = Array.get(array, 4);

final Class<?> myClass = arrayObjecy.getClass().getComponentType();

System.out.println(myClass);

arrayObj = Array.get(arrayObj, 10);

Array.setInt(arrayObj, 20, 50);

int arrayCast[][][] = (int[][][]) array;

System.out.println(arrayCast[3][5][10]);

}

}

利用反射机制修改对象

运行时变更field内容

与先前两个动作相比,“变更field内容”轻松多了,因为它不需要参数和自变量。首先调用Class的getField()并指定field名称。获得特定的Field object之后便可直接调用Field的get()和set()。

public class RefFiled {

public double x;

public Double y;

public static void main(String args[]) throws NoSuchFieldException, IllegalAccessException {

Class c = RefFiled.class;

Field xf = c.getField("x");

Field yf = c.getField("y");

RefFiled obj = new RefFiled();

System.out.println("变更前x=" + xf.get(obj));

//变更成员x值

xf.set(obj, 1.1);

System.out.println("变更后x=" + xf.get(obj));

System.out.println("变更前y=" + yf.get(obj));

//变更成员y值

yf.set(obj, 2.1);

System.out.println("变更后y=" + yf.get(obj));

}

}

标签: #python反射