文章目录
前言
一直对于反射很感兴趣,原本以为要到框架才能接触到,但往往计划没有变化快,今天终于接触到了心心念念的——反射了。year…
一、关于反射与注解的那些话(了解)
近十几年来,在Java和Android开发领域中涌现出许多优秀的框架,比如:Spring、Hibernate、Mybatis、Retrofit、Afinal、OKHttp、ButterKnife等等。这些框架的出现极大地简化了开发流程,提高了工作效率。在项目开发的过程中我们主要是使用这些轮子完成项目,很难有时间去顾及框架的内部实现。
1、反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
2、反射可以在一个类运行的时候获取类的信息的机制,可以获取在编译期不可能获得的类的信息。
3、对于任意一个对象,都能调用它的任意一个方法和属性。
4、因为类的信息是保存在Class对象中的,而这个Class对象是在程序运行时被类加载器(ClassLoader)动态加载的。
二、编程语言类型
1.静态类型语言
静态类型语言(Statically Typed Language)也称为强类型语言。在静态语言中,在编译时确定变量的数据类型。所以,绝大多数静态类型语言要求:先声明变量(即确定变量类型)后再使用变量。
常见的静态类型语言有:Java、 C、C++等等
2.动态类型语言
动态类型语言(Dynamic programming Language)也称为弱类型语言。在动态类型语言中,程序在运行时可以改变其结构;例如:改变变量原有的数据类型、新的函数被引进,已有的函数被删除等在结构上的变化。
常见的动态类型语言有:JavaScript、 PHP、Ruby等等。
2.1Java与动态性
Java程序的执行有两个阶段:
1、编译
2、运行
关于Java的编译、运行请参考:Java中字节码及其优势
在编译阶段会检查基本语法是否正确、变量的类型及其使用是否正确。程序在通过编译之后生成与之对应的字节码文件.class。JVM调用代码时,程序处于运行时状态。虽然说Java语言是静态类型语言,但是它在运行时借助反射从而具有了一定的动态性。所以,也有人说Java是”准动态类型语言”。
三、反射
1.反射的定义
Java的反射(Reflection)机制是指在程序运行时动态获取程序信息和动态调用对象的功能。反射是Java实现动态性的关键,其主要作用如下:
1、在运行时判断任意一个对象所属的类
2、在运行时构造任意一个类的对象
3、在运行时判断任意一个类所具有的成员变量和方法
4、在运行时调用任意一个对象的成员变量和方法
5、在运行时获取泛型信息
6、在运行时处理注解
7、在运行时生成动态代理
2.反射的应用场景
1、插件化编程
2、服务端编程
3、无.java源文件
4、获取类的所有信息
5、调用私有属性和方法
3.关于反射学习的进程的科学安排
1、ClassLoader
2、Class
3、Reflection API
四、类加载器
1.类加载器的分类
Java的类加载器有如下四种:
1、启动类加载器(Bootstrap Classloader)
2、扩展类加载器(Extension ClassLoader)
3、应用程序类加载器(Application Classloader)
4、自定义类加载器(User Classloader)
1.1启动类加载器(Bootstrap Classloader)
启动类加载器(Bootstrap Classloader)并不是java.lang.ClassLoder的子类,而是使用C/C++实现的。所以,无法通过Java代码获取启动类加载器。
代码如下(获取启动类加载器(Bootstrap Classloader) 代码演示):
public class GetBootstrapClassloader {
public static void main(String[] args) {
String string = "hello 反射!";
Class<? extends String> clazz = string.getClass();
ClassLoader classLoader = clazz.getClassLoader();
System.out.println(classLoader);
}
}
代码如下(获取启动类加载器(Bootstrap Classloader) 输出):
null
1.2扩展类加载器(Extension ClassLoader)
扩展类加载器(Extension ClassLoader)由sun.misc.Launcher$ExtClassLoader实现,它是java.lang.ClassLoader的子类。该类加载器负责加载Java的扩展库JAVA_HOME/jre/lib/ext/*.jar或者java.ext.dirs路径下的内容。
代码如下(获取扩展类加载器(Extension ClassLoader) 代码演示):
import java.io.File;
import java.util.StringTokenizer;
public class GetExtensionClassLoader {
public static void main(String[] args) {
String string = System.getProperty("java.ext.dirs");
StringTokenizer stringTokenizer = new StringTokenizer(string, File.pathSeparator);
int countTokens = stringTokenizer.countTokens();
File[] extDirs = new File[countTokens];
for(int i = 0;i<countTokens;i++) {
String nextToken = stringTokenizer.nextToken();
extDirs[i] = new File(nextToken);
System.out.println(extDirs[i]);
}
}
}
代码如下(获取启动类加载器(Bootstrap Classloader) 输出):
C:\Program Files\Java\jdk1.8.0_162\jre\lib\ext
C:\Windows\Sun\Java\lib\ext
1.3应用程序类加载器(Application Classloader)
应用程序类加载器(Application Classloader)由sun.misc.Launcher$AppClassLoader实现,它是java.lang.ClassLoader的子类。该类加载器负责加载Java应用程序类路径classpath或者java.class.path下的内容。也就是说:平常,我们在项目中自己写的类就是由应用程序类加载器加载进内存的。
代码如下(获取应用程序类加载器(Application Classloader) 代码演示):
public class GetApplicationClassLoader {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.classloader.Student");
ClassLoader classLoader = clazz.getClassLoader();
System.out.println(classLoader);
}
}
代码如下(获取应用程序类加载器(Application Classloader) 输出):
sun.misc.Launcher$AppClassLoader@6d06d69c
五、Class类
类加载器将类的.class文件加载进内存之后会在堆内存的方法区中产生Class类型的对象;该对象包含了类的所有结构信息。一个类有且只有一个Class对象,相同的类具有相同的Class对象 。我们只要获得了Class对象,就可以全面剖析一个类并可创建该类的对象且调用其方法。
1.在运行时类和接口对应的Class对象
代码如下(在运行时类和接口对应的Class对象 代码演示):
public class GetClass {
public static void main(String[] args) {
// 获取String类对应的class对象
Class<String> clazz01 = String.class;
// 获取Thread接口对应的class对象
Class<Thread> clazz02 = Thread.class;
System.out.println(clazz01);
System.out.println(clazz02);
}
}
代码如下(在运行时类和接口对应的Class对象 输出):
class java.lang.String
class java.lang.Thread
2.在运行时枚举和注释(即注解)也存在Class对象
代码如下(在运行时枚举和注释对应的Class对象 代码演示):
import java.lang.annotation.ElementType;
public class GetClass {
public static void main(String[] args) {
// 获取ElementType枚举对应的class对象
Class<?> clazz01 = ElementType.class;
// 获取Overridezhu注解对应的class对象
Class<?> clazz02 = Override.class;
System.out.println(clazz01);
System.out.println(clazz02);
}
}
代码如下(在运行时枚举和注释对应的Class对象 输出):
class java.lang.annotation.ElementType
interface java.lang.Override
3.在运行时,数组也存在相应的Class对象
代码如下(在运行时数组对应的Class对象 代码演示):
public class GetClass {
public static void main(String[] args) {
// 获取一维数组对应的class对象
Class<?> clazz01 = int[].class;
// 获取二维数组对应的class对象
Class<?> clazz02 = int[][].class;
System.out.println(clazz01);
System.out.println(clazz02);
}
}
代码如下(在运行时枚举和注释对应的Class对象 输出):
class [I
class [[I
4. 在运行时,Java基本数据类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象
代码如下(在运行时,Java基本数据类型关键字 void 也表示为 Class 对象 代码演示):
public class GetClass {
public static void main(String[] args) {
// 获取int的class对象
Class<?> clazz01 = int.class;
// 获取void对应的class对象
Class<?> clazz02 = void.class;
// 获取boolean对应的class对象
Class<?> clazz03 = boolean.class;
System.out.println(clazz01);
System.out.println(clazz02);
System.out.println(clazz03);
}
}
代码如下(在运行时,Java基本数据类型关键字 void 也表示为 Class 对象 输出):
int
void
boolean
5. 获取Class对象的方式小结
5.1 类型名.class
该方式适用于任意类型获取Class对象
代码如下(示例):
// 通过类型名.class获取class对象
public static void test01() {
Class<?> clazz01 = int.class;
Class<?> clazz02 = String.class;
System.out.println(clazz01);
System.out.println(clazz02);
}
代码如下(输出):
int
class java.lang.String
5.2 引用类型对象.getClass( )
因为只有引用类型才有对象;所以,该方式适用于引用类型获取Class对象
代码如下(示例):
// 通过引用类型对象.getClass()获取Class对象
public static void test02() {
String string = "时间带带";
Class<? extends String> clazz01 = string.getClass();
Object object = new Object();
Class<? extends Object> clazz02 = object.getClass();
System.out.println(clazz01);
System.out.println(clazz02);
}
代码如下(输出):
class java.lang.String
class java.lang.Object
5.3 Class.forName(“类的全限定名”)
该方式适用于除数组以外的引用类型数据获取Class对象
代码如下(示例):
// 通过Class.forName("类的全限定名")获取Class对象
public static void test03() {
Class<?> clazz01;
try {
clazz01 = Class.forName("java.lang.String");
System.out.println(clazz01);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
代码如下(输出):
class java.lang.String
5.4 类加载器对象.loadClass(“类的全限定名”)
该方式适用于除数组以外的引用类型数据获取Class对象。
代码如下(示例):
public static void test04() throws Exception {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
Class<?> loadClass = classLoader.loadClass("java.lang.String");
System.out.println(loadClass);
}
代码如下(输出):
class java.lang.String
六、Reflection API
1. 运行时获取类加载器
1.1 API
获取类加载器
ClassLoader java.lang.Class.getClassLoader()
1.2 运行时获取类加载器代码演示
代码如下(示例):
public class GetClassLoader {
public static void main(String[] args) {
// 获取String类的类加载器
Class<?> clazz01 = String.class;
ClassLoader classLoader01 = clazz01.getClassLoader();
// 获取Test1类的类加载器
Class<?> clazz02 = Test1.class;
ClassLoader classLoader02 = clazz02.getClassLoader();
System.out.println(classLoader01);
System.out.println(classLoader02);
}
}
代码如下(输出):
null
sun.misc.Launcher$AppClassLoader@6d06d69c
2. 运行时获取类的全限定名和包名
2.1 API
获取类的全限定名
String java.lang.Class.getName()
如果此类对象表示的是非数组类型的引用类型,则返回包.类名
如果此类对象表示一个基本类型或 void,则返回该基本类型或 void 所对应的 Java 语言关键字相同的字符串
如果此类对象表示一个数组类,则名字的内部形式为:表示该数组嵌套深度的一个或多个 ‘[’ 字符加元素类型名。其中,元素类型名的编码如下:
Element | Type Encoding |
---|---|
byte | B |
short | S |
int | I |
long | L |
float | F |
double | D |
boolean | Z |
char | C |
class or interface | Lclassname |
获取类所属包
Package java.lang.Class.getPackage()
获取类所属包的名称
String java.lang.Package.getName()
2.1 运行时获取类的全限定名和包名代码演示
代码如下(示例):
public class GetNameTest {
public static void main(String[] args) {
// 获取String类的class对象
Class<?> clazz01 = String.class;
// 获取String类的全限定名
String name = clazz01.getName();
// 获取String类的包名
String packageName = clazz01.getPackage().getName();
System.out.println("全限定名为:"+name);
System.out.println("包名为:"+packageName);
}
}
代码如下(输出):
全限定名为:java.lang.String
包名为:java.lang
3. 运行时获取类的修饰
3.1 API
获取类或接口的修饰符
int java.lang.Class.getModifiers()
获取类或接口的修饰符的字符串表示形式
String java.lang.reflect.Modifier.toString(int mod)
判断类或接口是否被public修饰
boolean java.lang.reflect.Modifier.isPublic(int mod)
3.2 运行时获取类的修饰代码演示
代码如下(示例):
import java.lang.reflect.Modifier;
public class Demo {
public static void main(String[] args) {
// 获取String类的class对象
Class<?> clazz01 = String.class;
// 获取String类的修饰符
int modifiers = clazz01.getModifiers();
// 将String类的修饰符转成字符串
String modifierString = Modifier.toString(modifiers);
// 判断String类是否被public修饰
boolean public1 = Modifier.isPublic(modifiers);
System.out.println(modifierString);
System.out.println(public1);
}
}
代码如下(输出):
public final
true
4. 运行时获取类的基本信息
4.1 API
获取类的父类
Class<? super Object> java.lang.Class.getSuperclass()
获取类实现的接口
Class<?>[] java.lang.Class.getInterfaces()
4.2 运行时获取类的基本信息代码演示
代码如下(示例):
import java.lang.reflect.Modifier;
public class Demo {
public static void main(String[] args) {
// 获取String类的class对象
Class<?> clazz01 = String.class;
// 获取String类的修饰符
int modifiers = clazz01.getModifiers();
// 将String类的修饰符转成字符串
String modifierString = Modifier.toString(modifiers);
// 判断String类是否被public修饰
boolean public1 = Modifier.isPublic(modifiers);
// 获取String类的父类
Class<?> superclass = clazz01.getSuperclass();
// 获取String类实现的接口
Class<?>[] interfaces = clazz01.getInterfaces();
for(Class<?> c:interfaces) {
System.out.println("String类实现的接口:"+c);
}
System.out.println("String类的父类:"+superclass);
System.out.println("String类的修饰符:"+modifierString);
System.out.println("关于String类的修饰是否被public修饰:"+public1);
}
}
代码如下(输出):
String类实现的接口:interface java.io.Serializable
String类实现的接口:interface java.lang.Comparable
String类实现的接口:interface java.lang.CharSequence
String类的父类:class java.lang.Object
String类的修饰符:public final
关于String类的修饰是否被public修饰:true
5. 运行时获取类的属性
5.1测试类(自己故意写的为了方便测试)
package com.Student;
public class Student {
public String name;
public String gender;
private int age;
public Student() {
}
public Student(String name, String gender, int age) {
super();
this.name = name;
this.gender = gender;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
5.2 API
获取类的所有公共属性
Field[] java.lang.Class.getFields() throws SecurityException
获取类的所有声明属性
Field[] java.lang.Class.getDeclaredFields() throws SecurityException
获取属性的名称
String java.lang.reflect.Field.getName()
获取属性类型
Class<?> java.lang.reflect.Field.getType()
获取属性修饰符
int java.lang.reflect.Field.getModifiers()
是否取消安全性检查
void java.lang.reflect.AccessibleObject.setAccessible(boolean flag) throws SecurityException
5.3 运行时获取类的属性代码演示
代码如下(示例):
package com.Student;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) {
// 获取自定义的Student类的Class对象
Class<?> clazz = Student.class;
// 获取自定义的Student类的公有属性
Field[] fields1 = clazz.getFields();
for(Field f:fields1) {
System.out.println("Student类的公有属性有:"+f);
// 获取Student类的公有属性的名称
String name = f.getName();
// 获取Student类的公有属性的类型
Class<?> type = f.getType();
// 获取Student类的公有属性的修饰符
int modifiers = f.getModifiers();
String modifierString = Modifier.toString(modifiers);
System.out.println("Student类的公有属性名称有:"+name);
System.out.println("Student类的公有属性类型有:"+type);
System.out.println("Student类的公有属性修饰符有:"+modifierString);
}
Field[] fields2 = clazz.getDeclaredFields();
for(Field f:fields2) {
System.out.println("Student类的声明属性有:"+f);
// 获取Student类的声明属性的名称
String name = f.getName();
// 获取Student类的声明属性的类型
Class<?> type = f.getType();
// 获取Student类的声明属性的修饰符
int modifiers = f.getModifiers();
String modifierString = Modifier.toString(modifiers);
System.out.println("Student类的声明属性名称有:"+name);
System.out.println("Student类的声明属性类型有:"+type);
System.out.println("Student类的声明属性修饰符有:"+modifierString);
}
}
}
代码如下(输出):
Student类的公有属性有:public java.lang.String com.Student.Student.name
Student类的公有属性名称有:name
Student类的公有属性类型有:class java.lang.String
Student类的公有属性修饰符有:public
Student类的公有属性有:public java.lang.String com.Student.Student.gender
Student类的公有属性名称有:gender
Student类的公有属性类型有:class java.lang.String
Student类的公有属性修饰符有:public
Student类的声明属性有:public java.lang.String com.Student.Student.name
Student类的声明属性名称有:name
Student类的声明属性类型有:class java.lang.String
Student类的声明属性修饰符有:public
Student类的声明属性有:public java.lang.String com.Student.Student.gender
Student类的声明属性名称有:gender
Student类的声明属性类型有:class java.lang.String
Student类的声明属性修饰符有:public
Student类的声明属性有:private int com.Student.Student.age
Student类的声明属性名称有:age
Student类的声明属性类型有:int
Student类的声明属性修饰符有:private
6. 运行时获取类的构造函数
6.1测试类(自己故意写的,为了方便测试)
public class Student {
private int age;
public String name;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
private Student(String name) {
super();
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
6.2 API
获取类的所有的公共构造器
Constructor<?>[] java.lang.Class.getConstructors() throws SecurityException
获取类的所有的声明构造器
Constructor<?>[] java.lang.Class.getDeclaredConstructors() throws SecurityException
获取指定的公共构造器
Constructor<Object> java.lang.Class.getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
获取指定的声明构造器
Constructor<Object> java.lang.Class.getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
获取构造器修饰符
int java.lang.reflect.Constructor.getModifiers()
获取构造器形参
Class<?>[] java.lang.reflect.Constructor.getParameterTypes()
6.3 运行时获取类的构造函数代码演示
代码如下(示例):
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Test {
public static void main(String[] args) {
// 获取运行时测试类Student对应的class对象
Class<?> clazz = Student.class;
// 获取测试类Student所有公共构造器
Constructor<?>[] constructors = clazz.getConstructors();
for(Constructor<?> c:constructors) {
// 获取构造器的名字
String name = c.getName();
System.out.println("公共构造器的名字都有"+name);
// 获取构造器的修饰符
int modifiers = c.getModifiers();
String modifierString = Modifier.toString(modifiers);
System.out.println("公共构造器的修饰符都有"+modifierString);
// 获取构造器的形参
Class<?>[] parameterTypes = c.getParameterTypes();
for(Class<?> p:parameterTypes) {
System.out.println("公共构造器的形参"+p);
}
}
System.out.println("------------------");
// 获取测试类Student所有声明(即这个类所有公有私有的构造器)构造器
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
for(Constructor<?> c:declaredConstructors) {
// 获取构造器的名字
String name = c.getName();
System.out.println("声明构造器的名字都有"+name);
// 获取构造器的修饰符
int modifiers = c.getModifiers();
String modifierString = Modifier.toString(modifiers);
System.out.println("声明构造器的修饰符都有"+modifierString);
// 获取构造器的形参
Class<?>[] parameterTypes = c.getParameterTypes();
for(Class<?> p:parameterTypes) {
System.out.println("声明构造器的形参"+p);
}
}
}
}
代码如下(输出):
公共构造器的名字都有Student
公共构造器的修饰符都有public
公共构造器的形参int
公共构造器的形参class java.lang.String
公共构造器的名字都有Student
公共构造器的修饰符都有public
------------------
声明构造器的名字都有Student
声明构造器的修饰符都有private
声明构造器的形参class java.lang.String
声明构造器的名字都有Student
声明构造器的修饰符都有public
声明构造器的形参int
声明构造器的形参class java.lang.String
声明构造器的名字都有Student
声明构造器的修饰符都有public
7. 运行时获取类的方法
7.1测试类(自己故意写的,为了方便测试)
import java.util.Date;
public class Student {
public String name;
public String gender;
private int age;
public Student() {
}
public Student(String name, String gender, int age) {
super();
this.name = name;
this.gender = gender;
this.age = age;
}
public int getAge() {
return age;
}
private void setAge(int age) {
this.age = age;
}
private String printInfo(String message) {
System.out.println("Star中的私有方法printInfo() 输入参数 message="+message);
String result="最新消息:"+message;
return result;
}
//static修饰的静态方法
public static void printDate() {
System.out.println(new Date());
}
}
7.2 API
获取该类及其父类的公共方法,但不能获取到私有方法
Method[] java.lang.Class.getMethods() throws SecurityException
获取该类本身所声明的所有方法
Method[] java.lang.Class.getDeclaredMethods() throws SecurityException
获取指定的公共方法
Method java.lang.Class.getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
获取指定的声明方法
Method java.lang.Class.getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
获取方法的名称
String java.lang.reflect.Method.getName()
获取方法修饰符
int java.lang.reflect.Method.getModifiers()
获取方法的返回值类型
Class<?> java.lang.reflect.Method.getReturnType()
获取方法的形参
Class<?>[] java.lang.reflect.Method.getParameterTypes()
获取方法抛出的异常
Class<?>[] java.lang.reflect.Method.getExceptionTypes()
7.3 运行时获取类的方法代码演示
7.3.1 获取该类及其父类的公共方法,但不能获取到私有方法
代码如下(示例):
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test1 {
public static void main(String[] args) {
// 获取自定义的Student类的Class对象
Class<?> clazz = Student.class;
// 获取自定义的Student及其父类的公共方法,但不能获取到私有方法
Method[] methods = clazz.getMethods();
for(Method m:methods) {
System.out.println("Student及其父类的公共方法:"+m);
// 获取Student类的方法的名称
String name = m.getName();
// 获取方法返回值类型
Class<?> returnType = m.getReturnType();
// 获取Student类的方法的修饰符
int modifiers = m.getModifiers();
String modifierString = Modifier.toString(modifiers);
// 获取方法的形参
Class<?>[] parameterTypes = m.getParameterTypes();
// 获取方法抛出的异常
Class<?>[] exceptionTypes = m.getExceptionTypes();
for(Class<?> exc:exceptionTypes) {
System.out.println("Student类所有公共方法的异常有:"+exc);
}
System.out.println("Student类的公共方法有:"+name);
System.out.println("Student类的公共方法返回值类型有:"+returnType);
System.out.println("Student类的公共方法的修饰符有:"+parameterTypes);
System.out.println("Student类的公共方法的形参有:"+modifierString);
}
}
}
代码如下(输出):
Student及其父类的公共方法:public int com.etime2.Student.getAge()
Student类的公共方法有:getAge
Student类的公共方法返回值类型有:int
Student类的公共方法的修饰符有:[Ljava.lang.Class;@33909752
Student类的公共方法的形参有:public
Student及其父类的公共方法:public static void com.etime2.Student.printDate()
Student类的公共方法有:printDate
Student类的公共方法返回值类型有:void
Student类的公共方法的修饰符有:[Ljava.lang.Class;@55f96302
Student类的公共方法的形参有:public static
Student及其父类的公共方法:public final void java.lang.Object.wait() throws java.lang.InterruptedException
Student类所有公共方法的异常有:class java.lang.InterruptedException
Student类的公共方法有:wait
Student类的公共方法返回值类型有:void
Student类的公共方法的修饰符有:[Ljava.lang.Class;@3d4eac69
Student类的公共方法的形参有:public final
Student及其父类的公共方法:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
Student类所有公共方法的异常有:class java.lang.InterruptedException
Student类的公共方法有:wait
Student类的公共方法返回值类型有:void
Student类的公共方法的修饰符有:[Ljava.lang.Class;@42a57993
Student类的公共方法的形参有:public final
Student及其父类的公共方法:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
Student类所有公共方法的异常有:class java.lang.InterruptedException
Student类的公共方法有:wait
Student类的公共方法返回值类型有:void
Student类的公共方法的修饰符有:[Ljava.lang.Class;@75b84c92
Student类的公共方法的形参有:public final native
Student及其父类的公共方法:public boolean java.lang.Object.equals(java.lang.Object)
Student类的公共方法有:equals
Student类的公共方法返回值类型有:boolean
Student类的公共方法的修饰符有:[Ljava.lang.Class;@6bc7c054
Student类的公共方法的形参有:public
Student及其父类的公共方法:public java.lang.String java.lang.Object.toString()
Student类的公共方法有:toString
Student类的公共方法返回值类型有:class java.lang.String
Student类的公共方法的修饰符有:[Ljava.lang.Class;@232204a1
Student类的公共方法的形参有:public
Student及其父类的公共方法:public native int java.lang.Object.hashCode()
Student类的公共方法有:hashCode
Student类的公共方法返回值类型有:int
Student类的公共方法的修饰符有:[Ljava.lang.Class;@4aa298b7
Student类的公共方法的形参有:public native
Student及其父类的公共方法:public final native java.lang.Class java.lang.Object.getClass()
Student类的公共方法有:getClass
Student类的公共方法返回值类型有:class java.lang.Class
Student类的公共方法的修饰符有:[Ljava.lang.Class;@7d4991ad
Student类的公共方法的形参有:public final native
Student及其父类的公共方法:public final native void java.lang.Object.notify()
Student类的公共方法有:notify
Student类的公共方法返回值类型有:void
Student类的公共方法的修饰符有:[Ljava.lang.Class;@28d93b30
Student类的公共方法的形参有:public final native
Student及其父类的公共方法:public final native void java.lang.Object.notifyAll()
Student类的公共方法有:notifyAll
Student类的公共方法返回值类型有:void
Student类的公共方法的修饰符有:[Ljava.lang.Class;@1b6d3586
Student类的公共方法的形参有:public final native
7.3.2 获取该类本身所声明的所有方法
代码如下(示例):
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test2 {
public static void main(String[] args) {
// 获取自定义的Student类的Class对象
Class<?> clazz = Student.class;
// 获取自定义的Student本身所声明的所有方法
Method[] methods = clazz.getDeclaredMethods();
for(Method m:methods) {
System.out.println("Student及其父类的本身所声明的所有方法:"+m);
// 获取Student类的方法的名称
String name = m.getName();
// 获取方法返回值类型
Class<?> returnType = m.getReturnType();
// 获取Student类的方法的修饰符
int modifiers = m.getModifiers();
String modifierString = Modifier.toString(modifiers);
// 获取方法的形参
Class<?>[] parameterTypes = m.getParameterTypes();
// 获取方法抛出的异常
Class<?>[] exceptionTypes = m.getExceptionTypes();
for(Class<?> exc:exceptionTypes) {
System.out.println("Student类所有本身所声明的所有方法的异常有:"+exc);
}
System.out.println("Student类的本身所声明的所有方法有:"+name);
System.out.println("Student类的本身所声明的所有方法返回值类型有:"+returnType);
System.out.println("Student类的本身所声明的所有方法的修饰符有:"+parameterTypes);
System.out.println("Student类的本身所声明的所有方法的形参有:"+modifierString);
}
}
}
代码如下(输出):
Student及其父类的本身所声明的所有方法:public int com.etime2.Student.getAge()
Student类的本身所声明的所有方法有:getAge
Student类的本身所声明的所有方法返回值类型有:int
Student类的本身所声明的所有方法的修饰符有:[Ljava.lang.Class;@5c647e05
Student类的本身所声明的所有方法的形参有:public
Student及其父类的本身所声明的所有方法:private void com.etime2.Student.setAge(int)
Student类的本身所声明的所有方法有:setAge
Student类的本身所声明的所有方法返回值类型有:void
Student类的本身所声明的所有方法的修饰符有:[Ljava.lang.Class;@33909752
Student类的本身所声明的所有方法的形参有:private
Student及其父类的本身所声明的所有方法:private java.lang.String com.etime2.Student.printInfo(java.lang.String)
Student类的本身所声明的所有方法有:printInfo
Student类的本身所声明的所有方法返回值类型有:class java.lang.String
Student类的本身所声明的所有方法的修饰符有:[Ljava.lang.Class;@55f96302
Student类的本身所声明的所有方法的形参有:private
Student及其父类的本身所声明的所有方法:public static void com.etime2.Student.printDate()
Student类的本身所声明的所有方法有:printDate
Student类的本身所声明的所有方法返回值类型有:void
Student类的本身所声明的所有方法的修饰符有:[Ljava.lang.Class;@3d4eac69
Student类的本身所声明的所有方法的形参有:public static
7.3.3 获取指定的公共方法
代码如下(示例):
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test3 {
public static void main(String[] args) throws Exception {
// 获取自定义的Student类的Class对象
Class<?> clazz = Student.class;
// 获取自定义的Student类的getAge方法
Method method = clazz.getMethod("getAge");
// 获取Student类的getAge方法的名称
String name = method.getName();
// 获取getAge方法返回值类型
Class<?> returnType = method.getReturnType();
// 获取Student类的getAge方法的修饰符
int modifiers = method.getModifiers();
String modifierString = Modifier.toString(modifiers);
// 获取getAge方法的形参
Class<?>[] parameterTypes = method.getParameterTypes();
// 获取getAge方法抛出的异常
Class<?>[] exceptionTypes = method.getExceptionTypes();
for (Class<?> exc : exceptionTypes) {
System.out.println("Student类getAge方法的异常有:" + exc);
}
System.out.println("Student类getAge方法的名字为:" + name);
System.out.println("Student类getAge方法返回值类型有:" + returnType);
System.out.println("Student类getAge方法的修饰符有:" + parameterTypes);
System.out.println("Student类getAge方法的形参有:" + modifierString);
}
}
代码如下(输出):
Student类getAge方法的名字为:getAge
Student类getAge方法返回值类型有:int
Student类getAge方法的修饰符有:[Ljava.lang.Class;@5c647e05
Student类getAge方法的形参有:public
7.3.4 获取指定的声明方法
代码如下(示例):
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test4 {
public static void main(String[] args) throws Exception {
// 获取自定义的Student类的Class对象
Class<?> clazz = Student.class;
// 获取自定义的Student类的setAge方法
Method declaredMethod = clazz.getDeclaredMethod("setAge", int.class);
// 获取Student类的setAge方法的名称
String name = declaredMethod.getName();
// 获取setAge方法返回值类型
Class<?> returnType = declaredMethod.getReturnType();
// 获取Student类的setAge方法的修饰符
int modifiers = declaredMethod.getModifiers();
String modifierString = Modifier.toString(modifiers);
// 获取setAge方法的形参
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
// 获取setAge方法抛出的异常
Class<?>[] exceptionTypes = declaredMethod.getExceptionTypes();
for (Class<?> exc : exceptionTypes) {
System.out.println("Student类setAge方法的异常有:" + exc);
}
System.out.println("Student类setAge方法的名字为:" + name);
System.out.println("Student类setAge方法返回值类型有:" + returnType);
System.out.println("Student类setAge方法的修饰符有:" + parameterTypes);
System.out.println("Student类setAge方法的形参有:" + modifierString);
}
}
代码如下(输出):
Student类setAge方法的名字为:setAge
Student类setAge方法返回值类型有:void
Student类setAge方法的修饰符有:[Ljava.lang.Class;@5c647e05
Student类setAge方法的形参有:private
8. 运行时创建类的对象
8.1测试类(自己故意写的,为了方便测试)
public class Student {
public String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
8.2 API
通过class.newInstance()调用无参构造函数创建对象
Object java.lang.Class.newInstance() throws InstantiationException, IllegalAccessException
通过constructor.newInstance()调用有参构造函数创建对象
T java.lang.reflect.Constructor.newInstance(Object... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
8.3 运行时创建类的对象代码演示
8.3.1 通过class.newInstance()调用无参构造函数创建对象
代码如下(示例):
public class Test1 {
public static void main(String[] args) throws Exception {
// 获取自定义的Student类的Class对象
Class<?> clazz = Student.class;
//通过class.newInstance()调用无参构造函数创建对象
Object newInstance = clazz.newInstance();
System.out.println("创建好的对象所在地址为:"+newInstance);
}
}
代码如下(输出):
创建好的对象所在地址为:com.et.Student@70dea4e
8.3.2 //通过constructor.newInstance()调用有参构造函数创建对象
代码如下(示例):
public class Test2 {
public static void main(String[] args) throws Exception {
// 获取自定义的Student类的Class对象
Class<?> clazz = Student.class;
// 通过constructor.newInstance()调用有参构造函数创建对象
Object newInstance = clazz.getConstructor(String.class,int.class).newInstance("小明",18);
System.out.println("创建好的对象所在地址为:"+newInstance);
}
}
代码如下(输出):
创建好的对象所在地址为:com.et.Student@70dea4e
9. 运行时操作对象的成员变量
9.1测试类(自己故意写的,为了方便测试)
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
public String name;
public String city;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, String city, int age) {
super();
this.name = name;
this.city = city;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", city=" + city + ", age=" + age + "]";
}
}
9.2 API
获取类的字段
Field java.lang.Class.getDeclaredField(String name) throws NoSuchFieldException, SecurityException
获取对象的成员变量的值
Object java.lang.reflect.Field.get(Object obj) throws IllegalArgumentException, IllegalAccessException
设置对象的成员变量的值
void java.lang.reflect.Field.set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException
9.3 运行时操作对象的成员变量代码演示
9.3.1 访问非静态成员变量
代码如下(示例):
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class TestField {
public static void main(String[] args) throws Exception {
Class<?> clazz = Student.class;
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class,String.class,int.class);
Object student = declaredConstructor.newInstance("张三","上海",18);
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
Object value = field.get(student);
System.out.println(value);
field.set(student, "llili");
System.out.println(student);
}
}
代码如下(输出):
张三
Student [name=llili, city=上海, age=18]
9.3.2 访问静态成员变量
代码如下(示例):
import java.lang.reflect.Field;
public class Test2 {
public static void main(String[] args) throws Exception {
Class<?> clazz = Student.class;
Field field = clazz.getDeclaredField("serialVersionUID");
field.setAccessible(true);
Object value = field.get(null);
System.out.println(value);
}
}
代码如下(输出):
1
10. 运行时操作对象的成员方法
10.1测试类(自己故意写的,为了方便测试)
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
public String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
10.2 API
访问成员方法
Object java.lang.reflect.Method.invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
10.3 运行时操作对象的成员方法代码演示
10.3.1 访问非静态成员方法
代码如下(示例):
import java.lang.reflect.Method;
public class Test1 {
public static void main(String[] args) throws Exception {
Class<?> clazz = Student.class;
Object student = clazz.newInstance();
Method declaredMethod = clazz.getDeclaredMethod("setName", String.class);
declaredMethod.invoke(student, "小红");
Method getMethod = clazz.getDeclaredMethod("getName");
Object value = getMethod.invoke(student);
System.out.println(value);
}
}
代码如下(输出):
小红
10.3.2 访问静态成员方法
代码如下(示例):
import java.lang.reflect.Method;
public class Test2 {
public static void main(String[] args) throws Exception {
Class<?> clazz = Student.class;
Method staticMethod = clazz.getDeclaredMethod("printDate");
Object value = staticMethod.invoke(null);
System.out.println(value);
}
代码如下(输出):
Tue Mar 16 20:24:11 CST 2021
null
总结
反射建立在运行时,这一点一定一定要记住,这是刚需
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/5064.html