java实验4 反射机制

要求:

1)严禁上网抄袭、互相抄袭和各种形式的抄袭(如代码抄袭,运行截图一图多用),一旦发现单次作业按零分处理!

2)课程报告正文内容基本格式为:宋体,小五号,1.5 倍行距。

3)作业报告请务必保持排版的整洁规范,排版混乱者将直接判为不及格。

4)为避免办公软件兼容性导致的显示差异问题,要求在提交课程报告 WORD 文件的同

时提交相应的 PDF 版本。

一、实验目的

  1. 掌握通过反射动态加载类、创建实例、访问和修改对象的私有字段、调用对象的方法等操作。

  2. 掌握如何通过反射获取注解的操作。

  3. 掌握反射与设计模式的使用。

  • 实验内容

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| public class Student { private String name; private int age; public Student() { this.name = "Unknown"; this.age = 0; } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void displayInfo() { System.out.println("Name: " + name + ", Age: " + age); } private void privateMethod() { System.out.println("Private method called"); } } |

  1. 使用反射对类进行相关的操作。创建一个简单类 Student包含私有字段 name 和 age。包含一个无参构造方法和一个带参构造方法。包含公共方法 getName()、getAge() 和 displayInfo()。包含一个私有方法 privateMethod()。

  2. 使用反射机制动态加载 Student 类。

  3. 使用反射机制创建 Student 类的实例。

  4. 使用反射机制访问和修改 Student 类的私有字段。

  5. 使用反射机制调用 Student 类的公共方法和私有方法。

代码:

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

public class ReflectionExample {

public static void main(String[] args) {

try {

// 动态加载Student类

Class<?> studentClass = Class.forName("Student");

// 使用无参构造函数创建Student实例

Student student1 = (Student) studentClass.getDeclaredConstructor().newInstance();

// 使用带参构造函数创建Student实例

Constructor<?> constructor = studentClass.getDeclaredConstructor(String.class, int.class);

Student student2 = (Student) constructor.newInstance("晓晓", 25);

// 访问和修改私有字段

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

nameField.setAccessible(true);

nameField.set(student2, "晓晓");

Field ageField = studentClass.getDeclaredField("age");

ageField.setAccessible(true);

ageField.setInt(student2, 20);

// 调用公共方法

Method displayInfoMethod = studentClass.getMethod("displayInfo");

displayInfoMethod.invoke(student2);

// 调用私有方法

Method privateMethod = studentClass.getDeclaredMethod("privateMethod");

privateMethod.setAccessible(true);

privateMethod.invoke(student2);

} catch (Exception e) {

e.printStackTrace();

}

}

}

运行截图:

  1. 有如下场景:项目的持久化层需要使用到的数据库有Redis、MySql、MongoDB。

要求:

  1. 定义一个DataService接口,接口提供add()、delete()、update()、find()四个接口,对应各种数据库的增删改查操作。
  2. 分别实现RedisDataService、MySqlDataService、MongoDBDataService。
  3. 通过反射机制,实现动态工厂模式
  4. 从配置文件中读取需要使用的数据库名称,如redis对应"RedisDataService"、MySql对应"MySqlDataService"、MongoDB对应"MySqlDataService"
  5. 实例化配置文件中所配置的数据库服务对象

其中项目的数据库至少需要选择一种,可选择多种;

配置文件格式如下,则代表项目需要两种类型的数据库,需要创建两个实例。

|--------------------------------------------------|
| MySql:MySqlDataService MongoDB: MySqlDataService |

代码:

public interface DataService {

void add();

void delete();

void update();

void find();

}

public class RedisDataService implements DataService {

public void add() { System.out.println("Adding via Redis"); }

public void delete() { System.out.println("Deleting via Redis"); }

public void update() { System.out.println("Updating via Redis"); }

public void find() { System.out.println("Finding via Redis"); }

}

public class MySqlDataService implements DataService {

public void add() { System.out.println("Adding via MySQL"); }

public void delete() { System.out.println("Deleting via MySQL"); }

public void update() { System.out.println("Updating via MySQL"); }

public void find() { System.out.println("Finding via MySQL"); }

}

public class MongoDBDataService implements DataService {

public void add() { System.out.println("Adding via MongoDB"); }

public void delete() { System.out.println("Deleting via MongoDB"); }

public void update() { System.out.println("Updating via MongoDB"); }

public void find() { System.out.println("Finding via MongoDB"); }

}

import java.util.Properties;

public class DataServiceFactory {

public static DataService getDataService(String serviceName) {

try {

Class<?> clazz = Class.forName(serviceName);

return (DataService) clazz.getDeclaredConstructor().newInstance();

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

}

MySql=MySqlDataService

MongoDB=MongoDBDataService

import java.io.FileInputStream;

import java.util.Properties;

public class Application {

public static void main(String[] args) {

try {

Properties properties = new Properties();

properties.load(new FileInputStream("config.properties"));

for (String key : properties.stringPropertyNames()) {

String className = properties.getProperty(key);

DataService service = DataServiceFactory.getDataService(className);

if (service != null) {

service.add();

service.delete();

service.update();

service.find();

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

运行截图:

  1. 通过反射和注解,自动生成接口文档。

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| public class UserController { public static class UserDTO { @ApiModelProperty("用户id") Integer userId; @ApiModelProperty("用户名称") String name ; } public static class UserVO { @ApiModelProperty("用户id") Integer userId; @ApiModelProperty("用户名称") String name; @ApiModelProperty("手机号") String phone; } @PostMapping("/get_user") public UserVO conf(UserDTO dto) { return new UserVO(); } } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ApiModelProperty { // 字段的注释 public String value() default ""; } |

要求:

  1. 实现自定义注解ApiModelProperty,用于字段描述。
  2. 实现自定义注解PostMapping,用于注明请求方法。
  3. UserDTO代表请求参数,UserVO对应响应参数。
  4. 使用反射机制获取注解信息,并生成一个接口文档,格式如下:

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 地址: http://localhost:8080/get_user 方法: post 请求参数: 字段名 类型 注释 userId integer 用户id name string 用户名称 返回参数: 字段名 类型 注释 userId integer 用户id Name string 用户名称 phone string 用户名称 |

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface ApiModelProperty {

String value() default "";

}

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface PostMapping {

String value() default "";

}

import java.lang.reflect.Field;

import java.lang.reflect.Method;

public class ApiDocumentationGenerator {

public static void generateDocumentation(Class<?> controllerClass) {

Method[] methods = controllerClass.getDeclaredMethods();

for (Method method : methods) {

if (method.isAnnotationPresent(PostMapping.class)) {

PostMapping postMapping = method.getAnnotation(PostMapping.class);

System.out.println("地址: http://localhost:8080" + postMapping.value());

System.out.println("方法: post");

Class<?>[] parameterTypes = method.getParameterTypes();

if (parameterTypes.length > 0) {

System.out.println("请求参数:");

System.out.println(" 字段名 类型 注释");

printFields(parameterTypes[0]);

}

Class<?> returnType = method.getReturnType();

System.out.println("返回参数:");

System.out.println(" 字段名 类型 注释");

printFields(returnType);

}

}

}

private static void printFields(Class<?> clazz) {

Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {

ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);

if (apiModelProperty != null) {

System.out.println(" " + field.getName() + " " + field.getType().getSimpleName().toLowerCase() + " " + apiModelProperty.value());

}

}

}

public static void main(String[] args) {

generateDocumentation(UserController.class);

}

}

三、思考题

  1. 反射机制实现动态代理的原理是什么?

++++反射机制实现动态代理的原理是在运行时创建代理类和对象,通过代理对象拦截对真实对象方法的调用,并允许在调用前后执行特定操作。这是通过 `java.lang.reflect.Proxy` 类和 `InvocationHandler` 接口实现的。++++

  1. 简述简单工厂设计模式与动态工厂设计模式的区别?

++++简单工厂设计模式是创建型模式,通过一个工厂类来创建不同类型的对象,客户端与具体产品解耦。动态工厂设计模式是简单工厂的扩展,它使用一个工厂方法来创建对象,允许在运行时动态决定创建何种产品。简单工厂在添加新产品时需要修改工厂类,而动态工厂通过继承或接口实现避免了这一点。++++

相关推荐
滴_咕噜咕噜2 分钟前
C#基础总结:常用的数据结构
开发语言·数据结构·c#
martian6652 分钟前
【Java高级篇】——第16篇:高性能Java应用优化与调优
java·开发语言·jvm
m0_748250034 分钟前
springboot使用logback自定义日志
java·spring boot·logback
-优势在我7 分钟前
Android TabLayout 实现随意控制item之间的间距
android·java·ui
Lojarro22 分钟前
JavaEE基础之- Servlet相关
java·servlet·java-ee
KingDol_MIni44 分钟前
Spring Boot 集成 T-io 实现客户端服务器通信
java·服务器·spring boot
许苑向上1 小时前
Java八股文(下)
java·开发语言
逸Y 仙X1 小时前
Git常见命令--助力开发
java·大数据·git·java-ee·github·idea
菜鸟一枚在这1 小时前
深入解析设计模式之单例模式
开发语言·javascript·单例模式
独孤求败Ace1 小时前
第44天:Web开发-JavaEE应用&反射机制&类加载器&利用链&成员变量&构造方法&抽象方法
java·开发语言