黑马程序员_高新技术-反射

本文深入介绍了Java反射机制的核心概念及应用,包括Constructor、Method、Field等类的使用方法,并通过实例演示了如何利用反射获取构造方法、操作字段及调用方法。此外,还对比了JDK1.4与JDK1.5中invoke方法的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

----------------------  ASP.Net+Unity开发 .Net培训 、期待与您交流! ----------------------
高新技术-反射

反射就 是把java类中的各种成分映射成相应的java类 。

Constructor

Method

Field

Package等等这些类代表的是字节码文件中的构造函数,字段,方法,包.。

用反射获取构造方法

Constructor constructor=String.class.getConstructor(StringBuffer.class);

用构造方法获取实例化对象

  String str=(String)constructor.newInstance(new StringBuffer("aaaa"));

用Class中的newInstance获取实例化对象

String str1=String.class.newInstance();

Field

private static void changeStringValue(Object obj)throws Exception {
  // TODO Auto-generated method stub
  Field[] fields = obj.getClass().getFields();
  for (Field field : fields) {

   //在这里用==比较确切,因为字节码文件在内存中只存在一份,所以用==比equals方法更合适
   if(field.getType() ==String.class){
    String oldValue=(String)field.get(obj);
    String newValue=oldValue.replace('b', 'a');
    field.set(obj, newValue);
   }
  }
 }

专家模式

谁拥有数据谁就是操作这个数据的专家

Method

  Method methodCharAt=String.class.getMethod("charAt", int.class);
  System.out.println(methodCharAt.invoke(str, 2));

invoke方法的第一人参数是对象,如果为null那么这个Method对象对应的是一个静态方法。

jdk1.4和jdk1.5中invoke方法的区别:
在方法中如果有参数是数组,1.5中是可变参数,1.4中是数组。
在传入的参数是数组时,在1.5中是Object类型的可变参数,而在1.4中是Object类型的数组。
如 public static void main(String[] args),要接收的是一个String类型的数组,而public static void main(String... args),要接收的是n个String类型的对象。
所以为了兼容1.4。我们在写程序的时候传入参数时,应该传一个数组而在1.5中编译器会将数组打开以可变参数的形式接收这个数组。所以在传入一个数组后,编译器会将数组打开,把打开后的每一个元素分别作为一个参数进行操作。这样在1.4中就会出现问题,因为将数组打开后的元素,就不再是这个方法要的参数,程序就会出错。那么我们可以将要传入的数组再封装到一个Object数组中,即mainMethod.invoke(null, new Object[]{new String[]{"111","222","3333"}});这样在打开这个数组之后,还是一个数组,就可以按照我们的思想把数组传递进去。或者将其转换成Objcet类型的数组,即mainMethod.invoke(null, (Object)new String[]{"111","222","3333"});这样是把String数组对象转换成了一个Object对象,就是告诉编译器,我传入的是一个对象不是一个数组,不需要打开。

数组的反射

int[] a1=new int[]{1,2,3,4};
  int[] a2=new int[3];
  int[][] a3=new int[2][3];
  String[] a4=new String[]{"a","b","c"};
  System.out.println(a1.getClass()==a2.getClass());
  //System.out.println(a1.getClass()==a3.getClass());
  //System.out.println(a1.getClass()==a4.getClass());
  System.out.println(a1.getClass().getName());
  System.out.println(a3.getClass().getName());
  System.out.println(a4.getClass().getName());
  System.out.println(a1.getClass().getSuperclass().getName());
  System.out.println(a3.getClass().getSuperclass().getName());
  System.out.println(a4.getClass().getSuperclass().getName());
  
  Object aobj1=a1;
  Object aobj2=a3;
  Object aobj3=a4;
  //Object[] aobj4=a1;//基本数据类型不是Object类
  Object[] aobj5=a3;
  Object[] aobj6=a4;
  
  System.out.println(Arrays.asList(a1,a4));
  System.out.println(Arrays.asList(a1));
  System.out.println(Arrays.asList(a4));

 

Array

是对数组进行反射的类

private static void printObject(Object obj) {
  // TODO Auto-generated method stub
  Class clazz=obj.getClass();
  if (clazz.isArray()) {
   int len=Array.getLength(obj);
   System.out.print("[");
   for (int i = 0; i < len; i++) {
    if(i<len-1)
     System.out.print(Array.get(obj, i)+", ");
    else
     System.out.println(Array.get(obj, i)+"]");
   }
  } else {
   System.out.println(obj);
  }
 }

反射的应用

一般在做框架的时候用

package cn.itcast.day1;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;

public class ReflectTest2 {

 /**
  * @param args
  */
 public static void main(String[] args)throws Exception {
  // TODO Auto-generated method stub
  //InputStream ips=new FileInputStream("src/cn/itcast/day1/config.properties");
  //只能读取配置文件
  //InputStream ips=ReflectTest2.class.getClassLoader().getResourceAsStream("resourse/config.properties");
  InputStream ips=ReflectTest2.class.getResourceAsStream("resourse/config.properties");
  Properties props=new Properties();
  props.load(ips);
  ips.close();
  String className=props.getProperty("className");
  Collection collection=(Collection)Class.forName(className).newInstance();
  
  ReflectPoint pt1=new ReflectPoint(3, 5);
  ReflectPoint pt2=new ReflectPoint(3, 3);
  ReflectPoint pt3=new ReflectPoint(3, 3);
  collection.add(pt1);
  collection.add(pt2);
  collection.add(pt3);
  
  System.out.println(collection.size());
  
  
 }

}

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------
### 关于JavaWeb部门管理模块的实现方法 在JavaWeb开发中,部门管理是一个常见的功能需求。通常情况下,该功能涉及增删改查(CRUD)操作。以下是针对修改部门这一具体场景的设计思路和代码示例。 #### 数据库设计 假设有一个`department`表用于存储部门信息,其结构如下: | 字段名 | 类型 | 描述 | |--------------|-------------|----------------| | id | INT PRIMARY KEY | 主键 | | name | VARCHAR(100) | 部门名称 | | description | TEXT | 部门描述 | #### 后端逻辑实现 ##### 控制器层 (Controller) 控制器负责接收前端传来的数据并调用服务层处理业务逻辑。以下是一个基于Spring MVC框架的示例: ```java @RestController @RequestMapping("/departments") public class DepartmentController { @Autowired private DepartmentService departmentService; /** * 修改部门信息接口 */ @PutMapping("/{id}") public ResponseEntity<String> updateDepartment(@PathVariable Integer id, @RequestBody Department department) { try { department.setId(id); departmentService.updateDepartment(department); return ResponseEntity.ok("更新成功"); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("更新失败:" + e.getMessage()); } } } ``` 上述代码实现了通过RESTful API的方式提供修改部门的功能[^2]。 ##### 服务层 (Service) 服务层主要封装具体的业务逻辑,例如校验输入参数、调用DAO层等。 ```java @Service public class DepartmentService { @Autowired private DepartmentDao departmentDao; public void updateDepartment(Department department) throws Exception { if (department == null || department.getId() == null) { throw new IllegalArgumentException("部门ID不能为空"); } int result = departmentDao.updateById(department); if (result != 1) { throw new RuntimeException("未找到对应的部门记录"); } } } ``` 此处的服务层采用了简单的异常抛出机制来确保错误能够被及时捕获并反馈给客户端[^3]。 ##### DAO层 (Data Access Object) DAO层专注于与数据库交互的操作。这里可以借助MyBatis框架简化SQL语句编写过程。 ```xml <!-- MyBatis Mapper XML --> <update id="updateById" parameterType="com.example.model.Department"> UPDATE department SET name = #{name}, description = #{description} WHERE id = #{id} </update> ``` 以上XML片段展示了如何利用MyBatis动态替换占位符从而执行更新查询[^4]。 #### 前端页面展示 对于前端部分,可以通过HTML+JavaScript组合或者采用Vue.js/Angular这样的现代前端框架构建用户界面。下面给出一个基本的例子: ```html <form onsubmit="return saveChanges();"> <input type="hidden" id="deptId" value="${department.id}"> 名称:<input type="text" id="deptName" value="${department.name}"><br><br> 描述:<textarea id="deptDesc">${department.description}</textarea><br><br> <button type="submit">保存更改</button> </form> <script> function saveChanges() { var deptId = document.getElementById('deptId').value; var deptName = document.getElementById('deptName').value; var deptDesc = document.getElementById('deptDesc').value; fetch(`/departments/${deptId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: deptName, description: deptDesc }) }).then(response => response.text()) .then(result => alert(result)); return false; // 阻止默认提交行为 } </script> ``` 此脚本允许管理员填写新的部门详情并通过AJAX请求发送至服务器进行持久化存储。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值