欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > Java 反射用法和8道练习题

Java 反射用法和8道练习题

2025/2/21 3:18:18 来源:https://blog.csdn.net/m0_53140426/article/details/140460277  浏览:    关键词:Java 反射用法和8道练习题

目录

  • 一、什么是反射
  • 二、反射的核心接口和类
  • 三、测试代码 Bean 类和目录结构
    • Person 类
    • 代码目录结构
  • 四、获取 Class 对象
  • 五、获取构造方法 Constructor 并使用
  • 六、获取成员变量 Field 并使用
  • 七、获取成员方法 Method 并使用
  • 八、练习
    • 1. 使用反射获取String类的所有公有方法,并把方法名打印出来。
    • 2. 使用反射创建一个对象,并调用其无参构造方法。
    • 3. 使用反射修改一个对象的私有字段值。
    • 4. 使用反射获取一个ArrayList的所有父类(包括间接父类)。
    • 5. 使用反射调用一个类的静态方法。
    • 6. 使用反射获取某个类的所有公有成员变量,并打印出每个成员变量的名称和类型。
    • 7. 使用反射获取某个类的所有成员方法,并打印出每个方法变量的名称和返回值类型。
    • 8. 使用反射调用一个对象的公有方法,并传递参数。

一、什么是反射

解释一:

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

解释二:
Java 反射是指在运行时动态检查和操作类的能力。通过反射,(对于一个对象)程序可以在运行时获取关于类、方法、属性、构造函数等的详细信息,并且可以动态地创建对象、调用方法以及访问和修改字段。反射提供了一种灵活的机制,使得程序可以在编译时不知道确切类型的情况下操作这些类型

二、反射的核心接口和类

Java 反射主要涉及以下几个核心类和接口,它们位于包 java.lang.reflect中:

Class:每个类和接口在 JVM 中都表示为一个 Class 对象。通过 Class 对象,程序可以获取类的全限定名、实现的接口、父类、构造函数、方法、字段等信息。
Constructor:表示类的构造函数。通过 Constructor 对象,程序可以创建类的新实例。
Field:表示类的属性。通过 Field 对象,程序可以获取或修改属性的值。
Method:表示类的方法。通过 Method 对象,程序可以调用方法。

三、测试代码 Bean 类和目录结构

Person 类

Person类有nameage属性,无参构造方法有参构造方法gettersettertoString以及自定义的sayHellosayGoodbye方法。

public class Person {private String name;private int age;public Person() {this.name = "unknown";this.age = 0;}public Person(String name, int age) {this.name = name;this.age = age;}// 省略getter()和setter()@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}// public类型public void sayHello() {System.out.println("Hello, my name is " + this.name);}// private类型private void sayGoodbye() {System.out.println("Goodbye, my name is " + this.name);}}

代码目录结构

在这里插入图片描述

四、获取 Class 对象

Class 对象包含了类的结构信息,是反射的入口点。获取 Class 对象有三种方法,如下所示:

1. 类.class
2. 对象.getClass()
3. Class.forName()

public class Main {public static void main(String[] args) {// 方式1: 类.class语法Class<?> cls1 = Person.class;System.out.println(cls1);               // class PersonSystem.out.println(cls1.getName());     // Person// 方式2: 对象.getClass()Class cls2 = new Person().getClass();System.out.println(cls2.getName());     // Person// 方式3: 使用静态方法Class.forName(),需要捕获ClassNotFoundExceptiontry {Class<?> cls3 = Class.forName("Person");System.out.println(cls3.getName()); // Person} catch (ClassNotFoundException e) {e.printStackTrace();}}
}

五、获取构造方法 Constructor 并使用

cls.getDeclaredConstructor()获取 Class 对象的所有构造方法
cls.getConstructor()获取 Class 对象的公有构造方法
constructor.newInstance()使用 Class 构造方法创建对象

import java.lang.reflect.Constructor;public class Main {public static void main(String[] args) {try {// 获取Person类的Class对象Class cls = Class.forName("Person");// Class personClass = Person.class;// Class personClass = new Person().getClass();// 获取无参构造方法Constructor<?> noArgsConstructor = cls.getConstructor();// 创建对象Object person1 = noArgsConstructor.newInstance();// 重写了Person的toString方法直接打印即可System.out.println(person1); // Person{name='unknown', age=0}// 获取带参数的构造方法Constructor<?> paramArgsConstructor = cls.getConstructor(String.class, int.class);// 创建对象,并传递参数Object person2 = paramArgsConstructor.newInstance("Alice", 30);System.out.println(person2); // Person{name='Alice', age=30}} catch (Exception e) {e.printStackTrace();}}
}

六、获取成员变量 Field 并使用

cls.getDeclaredField(name)获取 Class 对象的所有成员变量
cls.getField(name)获取 Class 对象的所有公有成员变量
field.setAccessible(true)设置 Class 对象的属性值可访问
field.get()获取 Class 对象的属性值
field.set()设置 Class 对象的属性值

import java.lang.reflect.Field;public class Main {public static void main(String[] args) {try {// 获取Person类的Class对象Class cls = Class.forName("Person");// Class personClass = Person.class;// Class personClass = new Person().getClass();// 创建Person对象Person person = new Person("Alice",30);// 获取name字段Field nameField = cls.getDeclaredField("name");// 设置可访问性,因为name是私有的nameField.setAccessible(true);// 获取name字段的值String name = (String) nameField.get(person);System.out.println("Name: " + name);        // Name: Alice// 获取age字段Field ageField = cls.getDeclaredField("age");// 设置可访问性,因为age是私有的ageField.setAccessible(true);// 获取age字段的值int age = ageField.getInt(person);System.out.println("Age: " + age);          // Age: 30// 修改age字段的值ageField.setInt(person, 31);// 再次获取age字段的值,验证修改是否成功age = ageField.getInt(person);System.out.println("Updated Age: " + age);  // Updated Age: 31} catch (Exception e) {e.printStackTrace();}}
}

七、获取成员方法 Method 并使用

cls.getDeclaredMethod(name)获取 Class 对象的所有成员方法
cls.getMethod(name)获取 Class 对象的公有成员方法
method.setAccessible(true)设置 Class 对象的方法可访问
method.invoke()调用 Class 对象的成员方法

import java.lang.reflect.Method;public class Main {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> cls = Class.forName("Person");// 创建Person对象Person person = (Person) cls.getDeclaredConstructor(String.class, int.class).newInstance("Alice", 30);//或 Person person =new Person("Alice", 30);// 获取sayHello方法Method sayHelloMethod = cls.getMethod("sayHello");// 调用sayHello方法sayHelloMethod.invoke(person);// 获取sayGoodbye方法Method sayGoodbyeMethod = cls.getDeclaredMethod("sayGoodbye");// 设置可访问性,因为sayGoodbye是私有的sayGoodbyeMethod.setAccessible(true);// 调用sayGoodbye方法sayGoodbyeMethod.invoke(person);} catch (Exception e) {e.printStackTrace();}}
}

八、练习

1. 使用反射获取String类的所有公有方法,并把方法名打印出来。

import java.lang.reflect.Method;public class Main {public static void main(String[] args) {Class<String> cls = String.class;Method[] methods = cls.getMethods();for (Method method : methods) {System.out.println(method.getName());}}
}

2. 使用反射创建一个对象,并调用其无参构造方法。

import java.lang.reflect.Constructor;public class Main {public static void main(String[] args) {Class<String> cls = String.class;try {Constructor<String> constructor = cls.getConstructor(String.class);// 指定了String就可以不用ObjectString s = constructor.newInstance("Hello world!");System.out.println(s);} catch (Exception e) {e.printStackTrace();}}
}

3. 使用反射修改一个对象的私有字段值。

import java.lang.reflect.Field;class Employee {private int age;public Employee() {}public Employee(int age) {this.age = age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}private void printAge() {System.out.println(this.age);}
}public class Main {public static void main(String[] args) {Employee employee = new Employee(30);Class cls = employee.getClass();try {Field ageField = cls.getDeclaredField("age");ageField.setAccessible(true);int age = ageField.getInt(employee);System.out.println(age);                // 30ageField.setInt(employee,31);System.out.println(employee.getAge());  // 31} catch (Exception e) {e.printStackTrace();}}
}

4. 使用反射获取一个ArrayList的所有父类(包括间接父类)。

import java.util.ArrayList;public class Main {public static void main(String[] args) {Class cls = ArrayList.class;while (cls != null) {System.out.println(cls.getName());cls = cls.getSuperclass();}}
}

5. 使用反射调用一个类的静态方法。

import java.lang.reflect.Method;class MyMath {public static <T extends Number> T add(T a, T b) {if (a instanceof Integer) {return (T) Integer.valueOf(a.intValue() + b.intValue());} else if (a instanceof Double) {return (T) Double.valueOf(a.doubleValue() + b.doubleValue());} else {throw new IllegalArgumentException("Unsupported number type");}}
}public class Main {public static void main(String[] args) {Class cls = MyMath.class;try {// 由于泛型擦除,需要指定方法的确切参数类型Method method = cls.getDeclaredMethod("add", Number.class, Number.class);// 静态方法必须指定nullObject invoke = method.invoke(null, 1, 2);System.out.println(invoke); // 3} catch (Exception e) {e.printStackTrace();}}
}

6. 使用反射获取某个类的所有公有成员变量,并打印出每个成员变量的名称和类型。

import java.lang.reflect.Field;class People {public int id;public int age;private String name;
}public class Main {public static void main(String[] args) {Class<People> cls = People.class;Field[] PeopleFields = cls.getFields();for (Field peopleField : PeopleFields) {System.out.println(peopleField.getName() + " => " + peopleField.getType());}//id => int//age => int}
}

7. 使用反射获取某个类的所有成员方法,并打印出每个方法变量的名称和返回值类型。

import java.lang.reflect.Method;class People {public void printHello() {System.out.println("Hello, Java");}public String getHello(String Hello) {return Hello + ", Java";}private int getMoney() {return 0;}}public class Main {public static void main(String[] args) {Class<People> cls = People.class;Method[] methods = cls.getDeclaredMethods();for (Method method : methods) {System.out.println(method.getName() + " => " + method.getReturnType());}//printHello => void//getHello => class java.lang.String//getMoney => int}
}

8. 使用反射调用一个对象的公有方法,并传递参数。

import java.lang.reflect.Method;class MyMath {public int add(int a, int b) {return a + b;}
}public class Main {public static void main(String[] args) {Class<MyMath> myMathClass = MyMath.class;try {Method addMethod = myMathClass.getMethod("add", int.class, int.class);MyMath myMath = new MyMath(); // 创建 MyMath 类的实例Object invoke = addMethod.invoke(myMath, 1, 2); // 传递 MyMath 类的实例System.out.println(invoke); // 3} catch (Exception e) {e.printStackTrace();}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词