第十六章总结

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

通过反射获取构造方法

1.获取构造方法:

1).批量的方法:

public Constructor[] getConstructors():所有"公有的"构造方法

public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

2).获取单个的方法,并调用:

public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:

public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

public class ConstructorDemo1 {

public static void main(String[] args) {

Demo1 d1 = new Demo1("10", "20", "30");

Class<? extends Demo1> demoClass = d1.getClass();

// 获得所有构造方法

Constructor[] declaredConstructors = demoClass.getDeclaredConstructors();

for (int i = 0; i < declaredConstructors.length; i++) { // 遍历构造方法

Constructor<?> constructor = declaredConstructors[i];

System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs());

System.out.println("该构造方法的入口参数类型依次为:");

Class[] parameterTypes = constructor.getParameterTypes(); // 获取所有参数类型

for (int j = 0; j < parameterTypes.length; j++) {

System.out.println(" " + parameterTypes[j]);

}

System.out.println("该构造方法可能抛出的异常类型为:");

// 获得所有可能抛出的异常信息类型

Class[] exceptionTypes = constructor.getExceptionTypes();

for (int j = 0; j < exceptionTypes.length; j++) {

System.out.println(" " + exceptionTypes[j]);

}

Demo1 d2 = null;

try { // 如果该成员变量的访问权限为private,则抛出异常,即不允许访问

if (i == 2) // 通过执行默认没有参数的构造方法创建对象

d2 = (Demo1) constructor.newInstance();

else if (i == 1)

// 通过执行具有两个参数的构造方法创建对象

d2 = (Demo1) constructor.newInstance("7", 5);

else { // 通过执行具有可变数量参数的构造方法创建对象

Object[] parameters = new Object[] { new String[] { "100", "200", "300" } };

d2 = (Demo1) constructor.newInstance(parameters);

}

} catch (Exception e) {

System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");

constructor.setAccessible(true); // 设置为允许访问

}

if (d2 != null) {

d2.print();

System.out.println();

}

}

}

}

package com.mr;

public class Demo1 {

String s;

int i, i2, i3;

private Demo1() {

}

protected Demo1(String s, int i) {

this.s = s;

this.i = i;

}

public Demo1(String... strings) throws NumberFormatException {

if (0 < strings.length)

i = Integer.valueOf(strings[0]);

if (1 < strings.length)

i2 = Integer.valueOf(strings[1]);

if (2 < strings.length)

i3 = Integer.valueOf(strings[2]);

}

public void print() {

// TODO Auto-generated method stub

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

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

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

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

}

}

import java.lang.reflect.Constructor;

import com.mr.Demo1;

//例题16.1

访问成员变量

package com.mr;

public class Demo2 {

int i;

public float f;

protected boolean b;

private String s;

}

//例题16.2

import java.lang.reflect.Field;

import com.mr.Demo2;

public class FieldDemo {

public static void main(String[] args) {

Demo2 example = new Demo2();

Class exampleC = example.getClass();

// 获得所有成员变量

Field[] declaredFields = exampleC.getDeclaredFields();

for (int i = 0; i < declaredFields.length; i++) { // 遍历成员变量

Field field = declaredFields[i];

System.out.println("名称为:" + field.getName()); // 获得成员变量名称

Class fieldType = field.getType(); // 获得成员变量类型

System.out.println("类型为:" + fieldType);

boolean isTurn = true;

while (isTurn) {

// 如果该成员变量的访问权限为private,则抛出异常,即不允许访问

try {

isTurn = false;

// 获得成员变量值

System.out.println("修改前的值为:" + field.get(example));

if (fieldType.equals(int.class)) { // 判断成员变量的类型是否为int型

System.out.println("利用方法setInt()修改成员变量的值");

field.setInt(example, 168); // 为int型成员变量赋值

} else if (fieldType.equals(float.class)) { // 判断成员变量的类型是否为float型

System.out.println("利用方法setFloat()修改成员变量的值");

field.setFloat(example, 99.9F); // 为float型成员变量赋值

// 判断成员变量的类型是否为boolean型

} else if (fieldType.equals(boolean.class)) {

System.out.println("利用方法setBoolean()修改成员变量的值");

field.setBoolean(example, true); // 为boolean型成员变量赋值

} else {

System.out.println("利用方法set()修改成员变量的值");

field.set(example, "MWQ"); // 可以为各种类型的成员变量赋值

}

// 获得成员变量值

System.out.println("修改后的值为:" + field.get(example));

} catch (Exception e) {

System.out.println("在设置成员变量值时抛出异常," + "下面执行setAccessible()方法!");

field.setAccessible(true); // 设置为允许访问

isTurn = true;

}

}

System.out.println();

}

}

}

3.访问成员方法

利用Method 对象可以操纵相应的方法:

1.getMethods().

2.getMethods(String name, Class<?>...parameterTypes).

3.getDeclaredMethods()

4.getDeclaredMethods(String name, Class<?>...parameterTypes)

如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。例如,访问一个为print、入口参数类型依次为 String 型和 nt型的方法,通过下面两种方式均可实现:

bjectClass.getDeclaredMethod("print", String.class, int.class);

objectClass.getDeclaredMethod("print", new Classl (String.class, int.class ));

//例题16.3

import java.lang.reflect.*;

import com.mr.Demo3;

public class MethondDemo {

public static void main(String[] args) {

Demo3 demo = new Demo3();

Class demoClass = demo.getClass();

// 获得所有方法

Method[] declaredMethods = demoClass.getDeclaredMethods();

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

Method method = declaredMethods[i]; // 遍历方法

System.out.println("名称为:" + method.getName()); // 获得方法名称

System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs());

System.out.println("入口参数类型依次为:");

// 获得所有参数类型

Class[] parameterTypes = method.getParameterTypes();

for (int j = 0; j < parameterTypes.length; j++) {

System.out.println(" " + parameterTypes[j]);

}

// 获得方法返回值类型

System.out.println("返回值类型为:" + method.getReturnType());

System.out.println("可能抛出的异常类型有:");

// 获得方法可能抛出的所有异常类型

Class[] exceptionTypes = method.getExceptionTypes();

for (int j = 0; j < exceptionTypes.length; j++) {

System.out.println(" " + exceptionTypes[j]);

}

boolean isTurn = true;

while (isTurn) {

try {// 如果该方法的访问权限为private,则抛出异常,即不允许访问

isTurn = false;

if ("staticMethod".equals(method.getName()))

method.invoke(demo); // 执行没有入口参数的方法

else if ("publicMethod".equals(method.getName()))

System.out.println("返回值为:" + method.invoke(demo, 168)); // 执行方法

else if ("protectedMethod".equals(method.getName()))

System.out.println("返回值为:" + method.invoke(demo, "7", 5)); // 执行方法

else if ("privateMethod".equals(method.getName())) {

Object[] parameters = new Object[] { new String[] { "M", "W", "Q" } }; // 定义二维数组

System.out.println("返回值为:" + method.invoke(demo, parameters));

}

} catch (Exception e) {

System.out.println("在执行方法时抛出异常," + "下面执行setAccessible()方法!");

method.setAccessible(true); // 设置为允许访问

isTurn = true;

}

}

System.out.println();

}

}

}

1.定义Annotation类型

1.在定义Annotation类型时,,也需要用到用来定义接口的 interface,

2.下面的代码定义了员工只包含一个Annotation类型

public @interface NoMenberAnnotation{

String value();

相关推荐
算法歌者1 分钟前
[算法]入门1.矩阵转置
算法
喵叔哟8 分钟前
重构代码之移动字段
java·数据库·重构
喵叔哟8 分钟前
重构代码之取消临时字段
java·前端·重构
fa_lsyk10 分钟前
maven环境搭建
java·maven
林开落L16 分钟前
前缀和算法习题篇(上)
c++·算法·leetcode
远望清一色17 分钟前
基于MATLAB边缘检测博文
开发语言·算法·matlab
tyler_download18 分钟前
手撸 chatgpt 大模型:简述 LLM 的架构,算法和训练流程
算法·chatgpt
封步宇AIGC24 分钟前
量化交易系统开发-实时行情自动化交易-3.4.1.2.A股交易数据
人工智能·python·机器学习·数据挖掘
何曾参静谧25 分钟前
「Py」Python基础篇 之 Python都可以做哪些自动化?
开发语言·python·自动化
Prejudices29 分钟前
C++如何调用Python脚本
开发语言·c++·python