java 反射习题_java学习之路 之 反射机制-练习题

反射机制练习题

前面我们对反射机制的理论知识进行了学习,现在我们来实际应用,从而更加了解它。首先我们先创建Person类,和Teacher类继承Person类(包含注解),供我们反射使用,具体如下:

package com.atguigu.javase.reflect;

import java.io.Serializable;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import org.junit.Test;

@Retention(RetentionPolicy.RUNTIME) // 保持在运行时,才可以通过反射获取

@interface MyAnn {

String name() default "张三";

int age() default 30;

}

// 创建Person类,为完成反射提供一个简单的类

class Person {

public String gender;

public int height;

public double weight;

private void privateTest() {

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

}

}

// 创建Teacher类继承Person类

@MyAnn

public class Teacher extends Person implements Serializable, Comparable {

private static int counter = 100;

public static void test() {

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

}

public String name;

private int age;

private double salary;

public Teacher() {

}

private Teacher(String name, int age, double salary) {

super();

this.name = name;

this.age = age;

this.salary = salary;

}

public void eat(String something) {

System.out.println("老师在吃" + something);

}

public void eat(String something, int time) {

System.out.println("老师在吃" + something + "吃了" + time + "小时");

}

@MyAnn(name="李四", age=40)

private static final String concat(int i, double d, char c, boolean b) {

return "" + i + d + c + b;

}

@Override

public String toString() {

return "Teacher [name=" + name + ", age=" + age + ", salary=" + salary + "]";

}

@Override

public int compareTo(Object o) {

return 0;

}

}现在我们就可以测试反射创建对象、调用属性、方法等和正常情况创建有什么区别?

package com.atguigu.javase.reflect;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.lang.annotation.Annotation;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.util.HashSet;

import java.util.Iterator;

import java.util.Properties;

import java.util.Set;

import org.junit.Test;

public class ReflectTest {

// 正常方式创建对象,调用方法

@Test

public void test1() {

/*

Teacher t1 = new Teacher(); // 由JVM自动 加载类, 再创建对象.

t1.name = "小明";

t1.age = 20;

t1.salary = 1000;

System.out.println(t1.name);

System.out.println(t1.age);

System.out.println(t1.salary);

t1.eat("回锅肉");

System.out.println(t1);

*/

}

// 通过反射获取类的属性,以及私有属性的获取

@Test

public void test2() {

try {

Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");// 根据类的全限定名称加载类并创建类模板对象,

//加载类的过程就是由类加载器读取Teacher.class二进制文件,由类加载器生成Class对象

// 类模板对象中包含了类中的属性的定义(Field对象)和方法的代码(Method对象)

Object object = clazz.newInstance(); // 对象的创建由方法来完成, 调用类的无参构造器创建对象

System.out.println(object);

//((Teacher)object).name = "小红";

//Field ageField = clazz.getField("age"); // 只能获取公共的属性

Field ageField = clazz.getDeclaredField("age"); // 只在在本类中声明了的属性, 就可以获取到!!!, 不受访问控制修饰

ageField.setAccessible(true);

ageField.set(object, 40);// 相当于object.age = 40;

System.out.println(ageField.get(object)); // System.out.println(object.age);

Field salaryField = clazz.getDeclaredField("salary");

System.out.println(salaryField);

salaryField.setAccessible(true); // 突破封装,实现私有成员的访问

salaryField.set(object, 5000);

System.out.println(salaryField.get(object));

Field nameField = clazz.getDeclaredField("name");

nameField.setAccessible(true); // 突破封装,实现私有成员的访问

nameField.set(object, "小红");

System.out.println(object);

} catch (ClassNotFoundException e) { // 类名不正确, 根据类名找到.class文件

e.printStackTrace();

} catch (InstantiationException e) { // 构造器调用错误!!

e.printStackTrace();

} catch (IllegalAccessException e) { // 构造器封装

e.printStackTrace();

} catch (NoSuchFieldException e) {

e.printStackTrace();

} catch (SecurityException e) {

e.printStackTrace();

}

}

// 通过反射获取类实现了哪些接口

@Test

public void test3() {

try {

Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");

Class superClazz = clazz.getSuperclass();

System.out.println(superClazz);

Class[] interfaceArr = clazz.getInterfaces();

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

System.out.println("实现接口:" + interfaceArr[i]);

}

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

// 创建对象的4种方法

@Test

public void test4() {

try {

//1) 常规使用, 软编码

Class clazz1 = Class.forName("com.atguigu.javase.reflect.Teacher");

//2) 最简单, 硬编码

Class clazz2 = Teacher.class;

System.out.println(clazz1 == clazz2);

//3) 比较灵活, 硬编码

Class clazz3 = new Teacher().getClass();

System.out.println(clazz2 == clazz3);

//4) 比较复杂, 先获取到类加载器对象,再手工加载类, 软编码

ClassLoader classLoader = this.getClass().getClassLoader();

Class clazz4 = classLoader.loadClass("com.atguigu.javase.reflect.Teacher");

System.out.println(clazz3 == clazz4);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

// 通过反射获取类加载器

@Test

public void test5() {

ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();

System.out.println(appClassLoader);

ClassLoader extClassLoader = appClassLoader.getParent();

System.out.println(extClassLoader);

ClassLoader bootstapClassLoader = extClassLoader.getParent();

System.out.println(bootstapClassLoader);

System.out.println("" + Object.class.getClassLoader());// 引导类加载器加载核心类

System.out.println("" + Person.class.getClassLoader());

}

@Test

public void test6() throws IOException {

// 通类加载器读取的资源文件的当前目录不是项目目录, 而是src目录

// src目录就是项目的classpath中的

// 可以直接从jar包中读取资源文件

//InputStream is = this.getClass().getClassLoader().getResourceAsStream("resource.properties");

InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/sun/corba/se/impl/logging/LogStrings.properties");

Properties properties = new Properties();

properties.load(is);

System.out.println(properties.getProperty("IOR.nullPoa"));

}

// 通过反射获取类的方法,并实现方法

@Test

public void test7() {

try {

Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");

Object object = clazz.newInstance();

Field nameField = clazz.getDeclaredField("name");

nameField.setAccessible(true);

nameField.set(object, "小明");

System.out.println(object);

// 调用方法

// 1) 从类模板对象中获取方法对象, getMethod会获取本类或者从父类继承的所有公共方式

Method eatMethod1 = clazz.getMethod("eat", String.class);

// 2) 通过方法对象间接调用自己

Object retValue = eatMethod1.invoke(object, "肉包子"); // object.eat("肉包子");

System.out.println("方法返回值:" + retValue);

Method eatMethod2 = clazz.getMethod("eat", String.class, int.class);

eatMethod2.invoke(object, "紫菜包饭", 5);

Method toStringMethod = clazz.getMethod("toString");

Object retValue2 = toStringMethod.invoke(object);

System.out.println(retValue2);

Method hashCodeMethod = clazz.getMethod("hashCode");

Object retValue3 = hashCodeMethod.invoke(object);

System.out.println(retValue3);

// 可以获取本类所有方法,包括私有方法

Method concatMethod = clazz.getDeclaredMethod("concat", int.class, double.class, char.class, boolean.class);

concatMethod.setAccessible(true);

Object retValue4 = concatMethod.invoke(object, 100, 3.14, '你', true);

System.out.println(retValue4);

System.out.println("修饰符:" + Modifier.toString(concatMethod.getModifiers()));

Annotation annotation = concatMethod.getAnnotation(Test.class); // 获取注解

System.out.println(annotation);

// getDeclaredMethod, 只能获取本类中声明的方法,从父类继承的无法拿到

//Method getClassMethod = clazz.getDeclaredMethod("getClass");

//System.out.println(getClassMethod);

// 获取父类的私有方法,并通过子类对象来调用, 也是可以成功的, 说明子类继承父类的所有成员!!

Method method = clazz.getSuperclass().getDeclaredMethod("privateTest");

method.setAccessible(true);

method.invoke(object);

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (NoSuchFieldException e) {

e.printStackTrace();

} catch (SecurityException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

}

// 通过反射获取构造器对象,从而完成对象的创建

@Test

public void test8() {

try {

Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");

// 使用其他构造器创建对象

// 1) 先获取到构造器对象

//Constructor constructor = clazz.getConstructor(String.class, int.class, double.class);

Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class, double.class);

int modifiers = constructor.getModifiers(); // 获取修饰符

Class[] typesClasses = constructor.getParameterTypes();

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

System.out.println("构造器参数:" + typesClasses[i]);

}

System.out.println(Modifier.toString(modifiers));

constructor.setAccessible(true);

// 2) 间接调用构造器完成对象创建

Object object = constructor.newInstance("立超", 19, 10000);

System.out.println(object);

Constructor runtimeConstructor = Runtime.class.getDeclaredConstructor();

System.out.println(runtimeConstructor);

runtimeConstructor.setAccessible(true);

Object object2 = runtimeConstructor.newInstance();

System.out.println(object2);

System.out.println(Runtime.getRuntime());

System.out.println(Object.class.getSuperclass());

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (SecurityException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

}

// 通过反射获取私有方法,注解

@Test

public void test9() {

try {

Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");

Annotation classannotation = clazz.getAnnotation(MyAnn.class);

System.out.println(classannotation);

// 可以获取本类所有方法,包括私有方法

Method concatMethod = clazz.getDeclaredMethod("concat", int.class, double.class, char.class, boolean.class);

System.out.println("修饰符:" + Modifier.toString(concatMethod.getModifiers()));

Annotation annotation = concatMethod.getAnnotation(MyAnn.class); // 获取注解

System.out.println(annotation);

} catch (Exception e) {

e.printStackTrace();

}

}

// 通过反射获取一个类的构造器,属性,方法

@Test

public void test10() throws Exception {

String className = "java.util.HashMap";

Class clazz = Class.forName(className);

Constructor[] allConstructors = clazz.getDeclaredConstructors(); // 本类中声明的所有构造器

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

System.out.println(allConstructors[i]);

}

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

Field[] allFields = clazz.getDeclaredFields(); // 本类中声明的所有的属性

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

System.out.println(allFields[i]);

}

Field[] allPublicFields = clazz.getFields(); // 获取本类及从父类继承的所有公共属性

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

System.out.println(allPublicFields[i]);

}

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

Method[] allMethods = clazz.getDeclaredMethods(); // 本类声明的所有方法

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

System.out.println(allMethods[i]);

}

Method[] allPublicMethods = clazz.getMethods(); // 获取本类及从父类继承的所有公共方法

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

System.out.println(allPublicMethods[i]);

}

}

// 写一个方法printClassDetails(String className)

// 先打印类名和父类(getSuperClass())及实现的接口(getInterfaces())

// 在方法中打印类模板中的所有构造器,所有属性(包含从父类继承的公共属性), 所有方法(包含从父类继承的公共方法) 要求不要重复打印

// 打印的时候注意一下缩进

public void printClassDetails(String className) throws ClassNotFoundException {

Class clazz = Class.forName(className);

System.out.print("public class " + clazz.getSimpleName() + " extends " + clazz.getSuperclass().getSimpleName());

System.out.print(" implements ");

Class[] allInterface = clazz.getInterfaces();

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

System.out.print(allInterface[i].getSimpleName() + ",");

}

System.out.println("{");

System.out.println();

Set allFields = new HashSet();

for (Field field : clazz.getFields()) {

allFields.add(field);

}

for (Field field : clazz.getDeclaredFields()) {

allFields.add(field);

}

Iterator iterator = allFields.iterator();

while (iterator.hasNext()) {

System.out.println("\t" + iterator.next());

}

System.out.println();

for (Constructor constructor : clazz.getDeclaredConstructors()) {

System.out.println("\t" + constructor);

}

System.out.println();

Set allMethods = new HashSet();

for (Method method : clazz.getMethods()) {

allMethods.add(method);

}

for (Method method : clazz.getDeclaredMethods()) {

allMethods.add(method);

}

System.out.println();

for (Method method : allMethods) {

System.out.println("\t" + method);

}

System.out.println("}");

}

// 调用printClassDetails方法

@Test

public void exer1() {

try {

printClassDetails("java.io.ObjectOutputStream");

} catch (Exception e) {

e.printStackTrace();

}

}

// 静态属性、静态方法的访问

@Test

public void test11() {

try {

Class clazz = Class.forName("com.atguigu.javase.reflect.Teacher");

//Object object = clazz.newInstance();

Field counterField = clazz.getDeclaredField("counter");

System.out.println(counterField);

counterField.setAccessible(true);

System.out.println(counterField.get(null)); // 静态属性的访问不需要对象, 所以传入null也可以

counterField.set(null, 10000); // 静态的设置也不需要对象

System.out.println(counterField.get(null)); // 静态属性的访问不需要对象, 所以传入null也可以

Method testMethod = clazz.getMethod("test");

testMethod.invoke(null);

} catch (Exception e) {

e.printStackTrace();

}

}

// 反射在自定义泛型中的应用

// 通过反射获取子类的泛型类型->创建父类对象

@Test

public void test12() throws InstantiationException, IllegalAccessException {

Parent parent1 = new Child1();

Parent parent2 = new Child2();

}

}// 上面test12测试所需要的类,其中父类为自定义泛型类,子类确定泛型的类型,在父类无参构造器中通过反射获取到子类的泛型// 类型从而确定父类的泛型类型,然后创建对象,从而实现对象的创建

class Parent {

T t;

Class clazz;

public Parent() {

Type type = this.getClass().getGenericSuperclass();

if (!(type instanceof ParameterizedType)) { // 在子类的声明中并没有任何的泛型信息

clazz = Object.class;

} else {

ParameterizedType parameteredType = (ParameterizedType)type;

Type[] types = parameteredType.getActualTypeArguments();

clazz = (Class)types[0];

}

System.out.println(clazz);

try {

t = (T) clazz.newInstance();

System.out.println(t);

} catch (InstantiationException | IllegalAccessException e) {

e.printStackTrace();

}

}

public T getT() {

return t;

}

}

class Child1 extends Parent {

}

class Child2 extends Parent {

}

class Child3 extends Parent {

}// 反射可以应用在泛型类中,但是更加凸显出去其作用是在动态中

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值