java反射判断方法存在_Java反射技术

反射

1,基本概念

反射库提供了一个精心设计的工具集,用来编写能够动态操纵Java代码的程序。能够分析类能力的程序成为反射。反射具有以下特性:

在运行时分析类的能力。

运行时查看对象。

实现通用的数组操作代码。

利用Method对象。

2.Class类

在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标示。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择响应的方法执行。这个信息被称为Class对象。

/**

* 反射

*/

public class ReflectDemo {

public static void main(String[] args) {

String s = "java.util.Random";

try {

// newInstance是Class对象的一个静态方法,可以获取当前类型的对象,

// 这个方法调用的是类的默认构造方法,如果没有默认构造会抛出异常信息

Object o = Class.forName(s).newInstance();

System.out.println("o = " + o );

} catch (Exception e) {

e.printStackTrace();

}

/*

获取类的Class对象(包括包路径)

3中获取类对象的方式

// 在知道类型时候获取Class对象

(1)Class cl = Integer.class;

// 在不知道类型的时候,但是存在该类型的变量的时候获取Class对象

(2) Integer a = 3;

Class cl1 = a.getClass();

// 完全不知道当前类型也不存在类的实例时获取Class对象

(3) Class cl2 = Class.forName(a); 此种方法存在异常必须要处理

*/

}

}

2.利用反射分析类的能力

这个是反射最强大的功能,他可以让我们在不知任何该类信息的时候,分析类的信息,并构建该类的对象并使用。

/**

* 反射

*/

public class ReflectDemo {

public static void main(String[] args) {

String name;

// 获取启动时参数,如果存在就使用启动时参数,否则输入自己的类名

if (args.length > 0) {

name = args[0];

}else {

Scanner in = new Scanner(System.in);

System.out.println("Enter class name(e.g. java.lang.String): ");

// 输入 java.lang.String 查看

name = in.next();

}

try {

Class c1 = Class.forName(name);

// 获取当前类的父类

Class superC1 = c1.getSuperclass();

// 返回当前类的所有修饰符

String modifiers = Modifier.toString(c1.getModifiers());

if (modifiers.length() > 0 ){

System.out.print(modifiers + " ");

}

System.out.print("class " + name);

if (superC1 != null && superC1 != Object.class) {

System.out.print(" extends " + superC1.getName());

}

System.out.println("\n{");

// 打印类的构造方法

printConstructors(c1);

System.out.println();

// 打印对象方法的有关信息

printMethods(c1);

System.out.println();

// 打印类实例域信息

printFields(c1);

System.out.println("}");

}catch (Exception e ){

e.getStackTrace();

}

}

/**

* 打印类实例域信息

* @param c1

*/

private static void printFields(Class c1) {

// 获取所有当前类的公有实例域,以及父类的公有实例域

Field[] field1 = c1.getFields();

// 获取所有当前类的实例域,以及父类的实例域

Field[] fields = c1.getDeclaredFields();

for (Field field : fields) {

// 获取实例域的类型

Class type = field.getType();

// 获取实例域的名称

String name = field.getName();

System.out.print(" ");

// 获取实例域的修饰符

String modifiers = Modifier.toString(field.getModifiers());

if (modifiers.length() > 0 ){

System.out.print(modifiers + " ");

}

System.out.println(type.getName() + " " + name + " ");

}

}

/**

* 打印对象方法的有关信息

* @param c1

*/

private static void printMethods(Class c1) {

// 获取所有当前类的公有方法,以及父类的公有方法

Method[] method1 = c1.getMethods();

// 获取所有当前类的方法,以及父类的方法,但不包括父类继承的方法

Method[] methods = c1.getDeclaredMethods();

for (Method m : methods) {

// 获取方法的返回值

Class type = m.getReturnType();

String name = m.getName();

System.out.print(" ");

// 获取方法的修饰符

String modifiers = Modifier.toString(m.getModifiers());

if (modifiers.length() > 0 ){

System.out.print(modifiers + " ");

}

System.out.print(type.getName() + " " + name + "(");

// 获取方法的所有参数类型

Class[] params = m.getParameterTypes();

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

if (i > 0) {

System.out.print(", ");

}

System.out.print(params[i].getName()+ " " + name + " ");

}

System.out.println(");");

}

}

/**

* 打印类的构造方法

* @param c1

*/

private static void printConstructors(Class c1) {

// 获取所有当前类的公有构造器

Constructor[] constructor1 = c1.getConstructors();

// 获取所有当前类的构造器

Constructor[] constructors = c1.getDeclaredConstructors();

for (Constructor constructor : constructors) {

// 获取构造方法的名称

String name = constructor.getName();

System.out.print(" ");

// 获取构造方法的修饰符

String modifys = Modifier.toString(constructor.getModifiers());

if (modifys.length() > 0 ) {

System.out.print(modifys + " ");

}

System.out.print(name + "(");

// 获取构造的所有参数类型

Class[] params = constructor.getParameterTypes();

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

if (i > 0) {

System.out.print(", ");

}

// 获取每个参数类型的名称

System.out.print(params[i].getName());

}

System.out.println(");");

}

}

}

3.在运行时使用反射分析对象

前面学习了如果在运行时查看任意对象所属类的信息,下面来讲一下如何在运行时,查看对象的具体信息。

亨达外汇http://www.kaifx.cn/broker/ha...

我以书中的通用toString方法来讲解:

import java.lang.reflect.AccessibleObject;

import java.lang.reflect.Array;

import java.lang.reflect.Field;

import java.lang.reflect.Modifier;

import java.util.ArrayList;

/**

* 编写通用的toString方法

*/

public class ToStringDemo {

/**

* 范型数组 暂时理解为相当于一个数组

*/

private ArrayList visited = new ArrayList<>();

/**

* 通用 toString方法

*

* @param object 传入任意对象

* @return 返回对象的信息

*/

public String toString(Object object) {

// 判断传入的对象是否为null

if (object == null) {

return "null";

}

// 判断该数组是否包含这个对象

if (visited.contains(object)) {

return "...";

}

// 获取该类的信息

Class cl = object.getClass();

// 判断是否是字符串类型,如果是直接返回字符串信息

if (cl == String.class) {

return (String) object;

}

// 判断是否是数组

if (cl.isArray()) {

// 只有数组才可以使用getComponentType()返回是什么类型的数组

// 如果不是数组将返回null

String r = cl.getComponentType() + "[]{";

// 遍历数组的长度

for (int i = 0; i < Array.getLength(object); i++) {

// 如果不是第一个就加个逗号

if (i > 0) {

r += ",";

}

// 获取数组中i位置的对象的值

Object val = Array.get(object, i);

// 判断当前数组类型是否是基本类型

if (cl.getComponentType().isPrimitive()) {

// 基本类型直接拼接

r += val;

} else {

// 不是基本类型,递归toString方法。判断对象类型是否数组类型

r += toString(val);

}

}

return r + "}";

}

// 获取类型的名称

String r = cl.getName();

do {

r += "[";

// 获取所有的实例域

Field[] fields = cl.getDeclaredFields();

// 设置访问权限,如果没有访问权限,Java安全机制只允许查看任意对象又那些域,而不允许读取他们的值

AccessibleObject.setAccessible(fields, true);

for (Field field : fields) {

// 判断实例域是否是静态的

if (!Modifier.isStatic(field.getModifiers())) {

if (!r.endsWith("[")) {

r += ",";

}

r += field.getName() + "=";

try {

// 获取实例域的类型

Class t = field.getType();

// 返回当前实例域的值

Object val = field.get(object);

// 判断该实例域是否是基本类型

if (t.isPrimitive()) {

r += val;

} else {

r += toString(val);

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

r += "]";

// 获取当前类是否具有父类

cl = cl.getSuperclass();

} while (cl != null);

return r;

}

public static void main(String[] args) {

// 创建一个数组

ArrayList squares = new ArrayList<>();

for (int i = 1; i <= 5; i++) {

squares.add(i * i);

}

System.out.println(squares.toString());

// 调用通用的toString方法

System.out.println(new ToStringDemo().toString(squares));

// 分析结果:

// 当前类包括elementData[] 和size的实例域

// java.util.ArrayList

// [

// elementData=

// class java.lang.Object[]

// 第一个[]代表当前的Integer的value值,第二个[]代表Integer的父类Number类,第三个[]代表着Number的父类Object类

// {java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},

// size=5

// ]

// ArrayList的父类 AbstractList类

// [modCount=5]

// AbstractList类 父类list类

// []

// list类的父类Object类

// []

}

}

4.通过反射调用任意方法

import java.lang.reflect.Method;

/**

* 利用反射调用任意方法

*/

public class ReflectMethodDemo {

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

// 返回ReflectMethodDemo类的square方法对象

Method square = ReflectMethodDemo.class.getMethod("square", double.class);

// 返回Math类的sqrt方法对象

Method sqrt = Math.class.getMethod("sqrt", double.class);

printTable(1,10,10,square);

printTable(1,10,10,sqrt);

}

public static double square(double x) {

return x * x;

}

public static void printTable(double from, double to, int n, Method f) {

System.out.println(f);

double dx = (to - from) / (n - 1);

for (double x = from; x <= to; x += dx) {

double y = 0;

try {

// 核心方法:执行调用法并返回方法的返回值

// 如果是静态方法,则第一个参数为null,不是静态方法表示调用对象要执行的方法

// 如果方法的返回值是基本类型,那么执行后真实的返回值是对应的包装类型,可以使用对应的自动拆箱转换称double类型

y = (Double) f.invoke(null,x);

System.out.printf("%10.4f | %10.4f%n",x, y);

} catch (Exception e) {

e.printStackTrace();

}

}

}

}5.反射编写数组

/**

* 泛型数组实例

*/

public class ArrayLIstDemo {

public static void main(String[] args) {

int[] a = {1,2,3};

a = (int[]) goodCopy(a,10);

System.out.println(Arrays.toString(a));

String[] b = {"Tom","Dick","Harry"};

b = (String[]) goodCopy(b,10);

System.out.println(Arrays.toString(b));

System.out.println("The following call will generate an exception.");

b = (String[]) badCopyOf(b,10);

}

/**

* 返回对象不能进行转换

* @param a

* @param newLength

* @return

*/

public static Object[] badCopyOf(Object[] a, int newLength){

Object[] newArray = new Object[newLength];

System.arraycopy(a,0,newArray,0,Math.min(a.length,newLength));

return newArray;

}

/**

* 利用反射获取类型并创建一个相同类型的数组在进行拷贝就可以了

* @param a

* @param newLength

* @return

*/

public static Object goodCopy(Object a, int newLength) {

Class cl = a.getClass();

if (!cl.isArray()) {

return null;

}

Class compoentType = cl.getComponentType();

int length = Array.getLength(a);

Object newArray = Array.newInstance(compoentType,newLength);

System.arraycopy(a, 0 , newArray,0,Math.min(length,newLength));

return newArray;

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值