目 录(本篇字数:1358)
· 简介
Java Reflection,称为 Java 反射,是Java基础部分的一个比较难的点。Reflection(反射)是被视为动态语言的关键,通过反射机制,我们可以在运行时(runtime)获取类的完整结构。例如,可以获取到类的变量名、方法、构造器、内部类、接口、注解等等,并且通过反射机制可以对类内部进行操作。
Java反射机制在实际开发中是非常常用的,强大一词完全可以用来形容它。作为Java基础内容的一部分,并且在很多开源框架(jdbc、spring、hibermate...)都使用到反射,可谓反射的重要性。
· 例子
首先,定义一个 Person 类及 Student 类,Student 继承自 Person 类,代码非常简单。如下:
package com.test;public class Person{ public String weight; public String height; public Person() { super(); } public Person(String weight, String height) { super(); this.weight = weight; this.height = height; } public String getWeight() { return weight; } public void setWeight(String weight) { this.weight = weight; } public String getHeight() { return height; } public void setHeight(String height) { this.height = height; } @Override public String toString() { return "Person [weight=" + weight + ", height=" + height + "]"; }}
package com.test;import java.io.Serializable;public class Student extends Personimplements Serializable, Runnable { public String stuNo; private String stuName; public Student() { super(); } public Student(String stuNo, String stuName) { super(); this.stuNo = stuNo; this.stuName = stuName; } public String getStuNo() { return stuNo; } public void setStuNo(String stuNo) { this.stuNo = stuNo; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } private int exam(String str, Integer tag) throws NoSuchMethodException { System.out.println(str); return tag; } @Override public String toString() { return "Student [stuNo=" + stuNo + ", stuName=" + stuName + "]"; } @Override public void run() { }}
有了这两个类,我们就可以开始利用反射来获取类的内部结构了。我们常规的创建对象操作:
@Test public void test() { Student student = new Student(); student.setStuNo("01"); student.setStuName("张三"); }
-
反射4种方式
在开始之前,我们来学习如何利用反射的方式来获取类的结构,反射的方式有这样 4 种。
* 反射的4种获取方式,反射的源头就是获取到一个 Class 对象进行操作类的内部方法和获取类的结构。
注意:父类中声明为 public 的变量、方法、接口等也可以被获取到。
@Test public void test() throws Exception { /** 第一种反射方式 */ Class clazz1 = new Student().getClass(); /** 第二种反射方式 */ Class clazz2 = Student.class; /** 第三种反射方式 */ // 先声明 xxx 类所在包的完整名 String className = "com.test.Student"; Class clazz3 = Class.forName(className); /** 第四种反射方式 */ Class clazz4 = this.getClass().getClassLoader().loadClass(className); }
以下都是利用反射来获取类结构的例子。
-
获取类中的变量,并进行赋值
@Test public void test() throws Exception { Class clazz = Student.class; Student student = (Student) clazz.newInstance(); /** 声明为 public 类型的变量可以这样获取 **/ Field field1 = clazz.getField("stuNo"); field1.set(student, "01"); System.out.println(student); /** 其他类型变量只能通过如下获取 **/ Field field2 = clazz.getDeclaredField("stuName"); field2.setAccessible(true); field2.set(student, "张三"); System.out.println(student); }
-
获取变量的权限修饰符(private、protected、public)
@Test public void test() throws Exception { Class clazz = Student.class; Student student = (Student) clazz.newInstance(); Field field1 = clazz.getField("stuNo"); Field field2 = clazz.getDeclaredField("stuName"); /** 获取 权限修饰符 **/ String str = Modifier.toString(field1.getModifiers()); System.out.println(str); String str2 = Modifier.toString(field2.getModifiers()); System.out.println(str2); }
-
获取类中的方法,并调用该方法(需注意权限修饰符)
-
获取类中方法的返回值
-
获取类中方法形参列表
-
获取类中方法异常类型
@Test public void test() throws Exception { Class clazz = Student.class; Student student = (Student) clazz.newInstance(); Method method = clazz.getMethod("setStuNo", String.class); method.invoke(student, "02"); System.out.println(student); /** 获取方法的返回值类型 */ Class returnType = method.getReturnType(); System.out.println(returnType); Method method2 = clazz.getDeclaredMethod("exam", String.class, Integer.class); method2.setAccessible(true); method2.invoke(student, "invoke exam method", 1); /** 获取方法的形参列表 */ Class[] params = method2.getParameterTypes(); for (Class param : params) { System.out.println(param); } /** 获取方法的异常类型 */ Class[] exceptions =method2.getExceptionTypes(); for(Class excp : exceptions) { System.out.println(excp); } }
-
获取类的完整包名、
-
类中所有的构造器、
-
类中实现的所有接口
@Test public void test() throws Exception { Class clazz = Student.class; Student student = (Student) clazz.newInstance(); //获取包名 System.out.println(clazz.getPackage()); /** * 获取 所有构造器 */ Constructor[] constructor = clazz.getDeclaredConstructors(); for(Constructor cons : constructor) { System.out.println(cons); } /** * 获取 所有接口 */ Class[] interfaces =clazz.getInterfaces(); for( Class its:interfaces) { System.out.println(its); } }
-
获取父类的结构
@Test public void test() throws Exception { Class clazz = Student.class; Student student = (Student) clazz.newInstance(); //获取父类 System.out.println(clazz.getSuperclass()); //获取带泛型的父类 Type type = clazz.getGenericSuperclass(); System.out.println(type); /** * 获取父类的泛型 */ Type type2 = clazz.getGenericSuperclass(); ParameterizedType args = (ParameterizedType)type2; Type[] types = args.getActualTypeArguments(); String t_Type = (String)types[0].getTypeName(); System.out.println(t_Type); }
以上的几个例子可以让我们知道反射的作用,反射能够在运行时状态下获取类的完整结构,在框架里显得尤为重要。
©原文链接:
@作者博客:
@更多博文: