枚举

为了间接的表示一些固定的值,Java就给我们提供了枚举是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内

定义格式

1
2
3
4
5
6
7
8
public enum s {
枚举项1,枚举项2,枚举项3;
}
注意: 定义枚举类要用关键字enum
/* 定义一个枚举类,用来表示春,夏,秋,冬这四个固定值 */
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER;
}

示例代码

1
2
3
4
5
6
7
8
9
10
11
public enum Season {
SPRING("春"),SUMMER,AUTUMN,WINTER("冬");
private String s =null;
private SeasonEnum(){}
private SeasonEnum(String s){
this.s = s;
}
public String getS(){
return s;
}
}
1
2
3
4
5
public class Test {
public static void main(String[] args) {
System.out.println(Season.SPRING.getS());
}
}

枚举的特点

  • 特点
    • 所有枚举类都是Enum的子类
    • 我们可以通过”枚举类名.枚举项名称”去访问指定的枚举项
    • 每一个枚举项其实就是该枚举的一个对象
    • 枚举也是一个类,也可以去定义成员变量
1
2
3
4
5
6
7
8
9
public class Test {
public static void main(String[] args) {
System.out.println(Season.SPRING);
System.out.println(Season.SUMMER);
System.out.println(Season.AUTUMN);
System.out.println(Season.WINTER);
Season spring = Season.SPRING;
}
}

枚举的方法

方法名 说明
String name() 获取枚举项的名称
int ordinal() 返回枚举项在枚举类中的索引值
int compareTo(E o) 比较两个枚举项,返回的是索引值的差值
String toString() 返回枚举常量的名称
static T valueOf(Class type,String name) 获取指定枚举类中的指定名称的枚举值
values() 获得所有的枚举项
1
2
3
public enum SeasonEnum {
SPRING,SUMMER,AUTUMN,WINTER;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class EnumDemo {
public static void main(String[] args) {
/* String name() 获取枚举项的名称 */
String name = SeasonEnum.SPRING.name();
System.out.println(name);
System.out.println("==============");
/* int ordinal() 返回枚举项在枚举类中的索引值 */
int index1 = SeasonEnum.SPRING.ordinal();
int index2 = SeasonEnum.SUMMER.ordinal();
int index3 = SeasonEnum.AUTUMN.ordinal();
int index4 = SeasonEnum.WINTER.ordinal();
System.out.println(index1);
System.out.println(index2);
System.out.println(index3);
System.out.println(index4);
System.out.println("==============");
/*int compareTo(E o) 比较两个枚举项,返回的是索引值的差值 */
int result = SeasonEnum.SPRING.compareTo(SeasonEnum.WINTER);
System.out.println(result);
System.out.println("===========");
/* String toString() 返回枚举常量的名称 */
String str = SeasonEnum.SPRING.toString();
System.out.println(str);
System.out.println("==========");
/* static <T> T valueOf(Class<T> type,String name) */
/* 获取指定枚举类中的指定名称的枚举值 */
SeasonEnum spring = Enum.valueOf(SeasonEnum.class, "SPRING");
System.out.println(spring);
System.out.println(SeasonEnum.SPRING == spring);
System.out.println("=========");
/* values() 获得所有的枚举项 */
SeasonEnum[] values = SeasonEnum.values();
for (SeasonEnum value:values) {
System.out.println(value);
}
}
}

注解

概述

  • 对我们的程序进行标注和解释

注解和注释的区别

  • 注释: 给程序员看的
  • 注解: 给编译器看的

使用注解进行配置配置的优势

  • 代码更加简洁,方便

java中的类,方法,变量,参数和包等都可以被标注。它们可以在编译、类加载、运行时被读取并执行相应的处理。

基本注解用法:

@Override 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

@Deprecated 标识方法过时 如果使用该方法,会报编译警告。

@SuppressWarnings 抑制警告,指示编译器去忽略注解中声明的警告。

自定义注解

格式

1
2
3
4
5
public @interface 注解名称 {

public 属性类型 属性名() default 默认值 ;

}

属性类型:基本数据类型,String,Class,注解,枚举,以上类型的一维数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public @interface AnnoTest {
/* 定义一个char类型的属性 */
public char ch() default '好';
/* 定义一个int类型的属性 */
int sum() default 1;
/* 定义一个String类型的属性 */
String str() default "好人";
/*定义String数组*/
String[] starr() default {"h","a","o"};
/* 定义一个枚举类型的属性 */
Season season() default Season.SPRING;
/* 定义一个注解类型的属性 */
Anno anno() default @Anno;
/* 定义一个Class类型的属性 */
Class clazz() default SeasonTest.class;
/*value。后期我们在使用注解的时候,如果我们只需要给注解的value属性赋值。
那么value就可以省略 */
public String value();
}

public @interface Anno {}

public enum Season {
SPRING,SUMMER,AUTUMN,WINTER;
}

注意:如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可

自定义注解案例

需求

  • 自定义一个注解@Test,用于指定类的方法上,如果某一个类的方法上使用了该注解,就执行该方法

实现步骤

  • 自定义一个注解Test,并在类中的某几个方法上加上注解
  • 在测试类中,获取注解所在的类的Class对象
  • 获取类中所有的方法对象
  • 遍历每一个方法对象,判断是否有对应的注解

代码实现

1
2
3
4
5
6
7
8
9
10
11
/* 表示Test这个注解的存活时间 */
/* RetentionPolicy.SOURCE —— 只在源文件中,编译后丢弃
RetentionPolicy.CLASS —— 编译后保留在class中,但被JVM丢弃
RetentionPolicy.RUNTIME —— 被JVM保留,所以他们能在运行时被JVM或其他使用反射机
制的代码所读取和使用.
*/

@Retention(RetentionPolicy.RUNTIME)
public @interface Anno {

}
1
2
3
4
5
6
7
8
9
10
11
public class Utils {
/* 没有使用Test注解 */
public void hao(){
System.out.println("好人");
}
/* 使用Test注解 */
@Anno
public void method(){
System.out.println("启动");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
/* 1.通过反射获取UseTest类的字节码文件对象 */
Class clazz = Class.forName("com.example.qy161_backstage.Utils");
/* 创建对象 */
Utils utils = (Utils) clazz.getDeclaredConstructor().newInstance();
/* 2.通过反射获取这个类里面所有的方法对象 */
Method[] method = clazz.getDeclaredMethods();
/* 3.遍历数组,得到每一个方法对象 */
for (Method methods : method) {
/* method依次表示每一个方法对象。
isAnnotationPresent(Class<? extends Annotation> annotationClass)
判断当前方法上是否有指定的注解。
参数:注解的字节码文件对象
返回值:布尔结果。 true 存在 false 不存在 */
if (methods.isAnnotationPresent(Anno.class)){
methods.invoke(utils);
}
}
}
}

元注解

概述

  • 元注解就是描述注解的注解

  • 元注解介绍

元注解名 说明
@Target 指定了注解能在哪里使用
@Retention 可以理解为保留时间(生命周期)
@Inherited 表示修饰的自定义注解可以被子类继承
@Documented 表示该自定义注解,会出现在API文档里面
1
2
3
4
5
6
7
8
/* @Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})
指定注解使用的位置(成员变量,类,方法)
@Retention(RetentionPolicy.RUNTIME)
指定该注解的存活时间
@Inherited 指定该注解可以被继承 */
@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Anno {}
1
2
3
@Anno
public class Person {
}
1
2
3
4
5
public class Student extends Person {
public void show(){
System.out.println("student.......show..........");
}
}
1
2
3
4
5
6
7
8
9
public class StudentDemo {
public static void main(String[] args) throws ClassNotFoundException {
/* 获取到Student类的字节码文件对象 */
Class clazz = Class.forName("com.aaa.myanno4.Student");
/* 获取注解 */
boolean result = clazz.isAnnotationPresent(Anno.class);
System.out.println(result);
}
}

反射

反射概念:

  • 通常情况下编写代码都是固定的,无论运行多少次执行的结果也是固定的,在某些特殊场合中编写 代码时不确定要创建什么类型的对象,也不确定要调用什么样的方法,这些都希望通过运行时传递 的参数来决定,该机制叫做动态编程技术,也就是反射机制。

  • 通俗来说,反射机制就是用于动态创建对象并且动态调用方法的机制。

  • 目前主流的框架底层都是采用反射机制实现的。

类加载器

负责将.class文件(存储的物理文件)加载在到内存中

xxx.java –javac–> xxx.class –(类加载器)–>虚拟机

类加载的过程【理解】

  • 类加载时机

    • 创建类的实例(对象)–> new
    • 调用类的类方法 – >静态方法
    • 访问类或者接口的类变量,或者为该类变量赋值 –>静态变量
    • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象–> 反射
    • 初始化某个类的子类 –> 创建子类
    • 直接使用java.exe命令来运行某个主类 –> main 函数
  • 类加载过程

    • 加载
      • 通过包名 + 类名,获取这个类
      • 把这个类加载到内存中
      • 加载完毕创建一个class对象
    • 链接
      • 验证:确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全(文件中的信息是否符合虚拟机规范有没有安全隐患)
      • 准备:负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值,(初始化静态变量)
      • 解析:将类的二进制数据流中的符号引用替换为直接引用(本类中如果用到了其他类,此时就需要找到对应的类)
    • 初始化
      • 根据程序员通过程序制定的主观计划去初始化类变量和其他资源,(静态变量赋值以及初始化其他资源)
  • 小结

  • 当一个类被使用的时候,才会加载到内存

  • 类加载的过程: 加载、验证、准备、解析、初始化

类加载的分类【理解】

  • 分类
    • Bootstrap class loader:虚拟机的内置类加载器,通常表示为null ,并且没有父null 启动类加载器
    • Platform class loader:平台类加载器,负责加载JDK中一些特殊的模块在,Java8和之前,这个加载器叫做扩展加载器(ExtClassLoader)
    • System class loader:系统类加载器,负责加载用户类路径上所指定的类库,也叫Appclass Loader
  • 类加载器的继承关系
    • System的父加载器为Platform
    • Platform的父加载器为Bootstrap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ClassLoaderTest {
public static void main(String[] args) {
/* 获取系统类加载器 */
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
/* 获取系统类加载器的父加载器 --- 平台类加载器 */
ClassLoader parent = systemClassLoader.getParent();
/* 获取平台类加载器的父加载器 --- 启动类加载器 */
ClassLoader parent1 = parent.getParent();

System.out.println("系统类加载器" + systemClassLoader);
System.out.println("平台类加载器" + parent);
System.out.println("启动类加载器" + parent1);
}
}

双亲委派模型【理解】

概念:如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式

ClassLoader类

方法名 说明
public static ClassLoader getSystemClassLoader() 获取系统类加载器
public InputStream getResourceAsStream(String name) 加载某一个资源文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ClassLoaderDemo2 {
public static void main(String[] args) throws IOException {
/*static ClassLoader getSystemClassLoader() 获取系统类加载器
InputStream getResourceAsStream(String name) 加载某一个资源文件*/
/* 获取系统类加载器 */
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
/* 利用加载器去加载一个指定的文件
参数:文件的路径(放在src的根目录下,默认去那里加载)
返回值:字节流 */
InputStream is = systemClassLoader.getResourceAsStream("prop.properties");
Properties prop = new Properties();
prop.load(is);
System.out.println(prop);
is.close();
}
}

Class类

Class基本概念

java.lang.Class类的实例可以用于描述Java应用程序中的类和接口,也就是一种数据类型。 该类没有公共构造方法,该类的实例由Java虚拟机和类加载器自动构造完成,本质上就是加载到内存中的运行时类。

获取Class对象的方式

  • 使用数据类型.class的方式可以获取对应类型的Class对象(掌握)。

  • 使用引用/对象.getClass()的方式可以获取对应类型的Class对象。

  • 使用包装类.TYPE的方式可以获取对应基本数据类型的Class对象。

  • 使用Class.forName()的方式来获取参数指定类型的Class对象(掌握)。

  • 使用类加载器ClassLoader的方式获取指定类型的Class对象。

常用的方法

方法声明 功能介绍
static Class<?> forName(String className) 用于获取参数指定类型对应的Class对象并返回
T newInstance() [方法已过时] 用于创建该Class对象所表示类的新实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class ClassTest {
public static void main(String[] args) throws ClassNotFoundException {
/* 1.使用数据类型.class的方式可以获取对应类型的Class对象*/
Class c1 = String.class;
System.out.println("c1:"+c1);
// 自动调用toString方法 class java.lang.String
c1= int.class;
System.out.println("c1: "+c1);
c1 = void.class;
System.out.println("c1: "+c1);
System.out.println("=============");
/* 2.使用对象.getClass()的方式获取对应的Class对象 */
String str1 = new String("hello");
c1=str1.getClass();
System.out.println("c1: "+c1);
//int.getClass(); Error: 基本数据类型的变量不能调用方法
Integer it1 = 20;
c1 = it1.getClass();
System.out.println("c1: "+c1);
System.out.println("=============");
/* 4.调用Class类中的forName方法来获取对应的Class对象*/
//要求写完整的名称:包名.类名
//不能获取基本数据类型的Class对象
c1 = Class.forName("java.util.Date");
System.out.println("c1: "+c1);
System.out.println("=============");
/* 5.使用类加载器的方式来获取Class对象 */
ClassLoader classLoader = ClassTest.class.getClassLoader();
System.out.println("classLoader = " + classLoader);
c1 = classLoader.loadClass("java.lang.String");
System.out.println("c1 = " + c1);

}
}

Constructor类

概念:java.lang.reflect.Constructor类主要用于描述获取到的构造方法信息

Class类获Constructor类的方法

方法声明 功能介绍
Constructor getConstructor(Class<>…parameterTypes) 用于获取此Class对象所表示类型中参数指定的
Constructor<?>0getConstructors() 用于获取此Class对象所表示类型中所有的公共

Constructor类的常用方法

方法声明 功能介绍
T newInstance(Object…initargs) 使用此Constructor对象描述的构造方法来构造Class对象代表类型的新实例
int getModifiers() 获取方法的访问修饰符
String getName() 获取方法的名称
Class<?[]getParameterTypes() 获取方法所有参数的类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Person {
private String name;
public Person() {}

public Person(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ConstructorTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Person person = new Person();
Class aClass = Class.forName("com.example.qy161_backstage.reflex.Person");
Constructor constructors = aClass.getConstructor();
Object o = constructors.newInstance();
System.out.println(o);

Person person1 = new Person("hd");
Class aClass1 = Class.forName("com.example.qy161_backstage.reflex.Person");
Constructor constructors1 = aClass.getConstructor(String.class);
Object hd1 = constructors1.newInstance("hd1");
System.out.println(hd1);

Person person2 = new Person();
Class aClass2 = Class.forName("com.example.qy161_backstage.reflex.Person");
Constructor[] constructors2 = aClass2.getConstructors();
for (int i = 0; i < constructors2.length; i++) {
Constructor constructor = constructors2[i];
System.out.println(constructor);
System.out.println("==========================");
System.out.println(constructor.getModifiers());
System.out.println(constructor.getName());
System.out.println(constructor.getParameterTypes());
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class PersonConstructorTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/* 1.使用原始方式以无参形式构造Person类型的对象并打印 */
Person p1 = new Person();
System.out.println("无参方式创建的对象是:" + p1);
System.out.println("-------------------------------");
/* 2.使用反射机制以无参形式构造Person类型的对象并打印 */
/* 创建对象的类型可以从键盘输入
System.out.println("请输入要创建对象的类型:");
Scanner sc = new Scanner(System.in);
String str1 = sc.next();
Class c1 = Class.forName("com.aaa.Person");*/
/* 创建对象的类型可以从配置文件中读取 */
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:/.Code/aaa.txt")));
String str1 = br.readLine();
// Class aClass2 =Class.forName("com.example.qy161_backstage.reflex.Person");
Class c1 = Class.forName(str1);
//System.out.println("无参方式创建的对象是:" + c1.newInstance());
/* 获取Class对象对应类中的无参构造方法,也就是Person类中的无参构造方法 */
Constructor constructor = c1.getConstructor();
/* 使用获取到的无参构造方法来构造对应类型的对象,也就是Person类型的对象 */
System.out.println("无参方式创建的对象是:" + constructor.newInstance());
br.close();
System.out.println("-------------------------------");
/* 4.使用反射机制以有参方式构造Person类型的对象并打印 */
/* 获取Class对象对应类中的有参构造方法,也就是Person类中的有参构造方法 */
Constructor constructor1 = c1.getConstructor(String.class);
/* 使用获取到的有参构造方法来构造对应类型的对象,也就是Person类型的对象 */
/* newInstance方法中的实参是用于给有参构造方法的形参进行初始化的,也就是给name和age进行初始化的 */
System.out.println("有参方式构造的对象是:" + constructor1.newInstance("zhangfei"));
System.out.println("-------------------------------");
/* 5.使用反射机制获取Person类中所有的公共构造方法并打印 */
Constructor[] constructors = c1.getConstructors();
for (Constructor ct : constructors) {
System.out.println("构造方法的访问修饰符是:" + ct.getModifiers());
System.out.println("构造方法的方法名称是:" + ct.getName());
Class[] parameterTypes = ct.getParameterTypes();
System.out.print("构造方法的所有参数类型是:");
for (Class cs : parameterTypes) {
System.out.print(cs + " ");
}
System.out.println();
System.out.println("-------------------------------");
}
}
}

Field类

基本概念:java.lang.reflect.Field类主要用于描述获取到的单个成员变量信息

获取到Field类的方法

方法声明 功能介绍
Field getDeclaredField(String name) 用于获取此Class对象所表示类中参数指定的单个成员变量信息
Field[ getDeclaredFields() 用于获取此Class对象所表示类中所有成员变量信息

Field类的常用方法

方法声明 功能介绍
Object get(Object obj) 获取参数对象obj中此Field对象所表示成员变量的数值
void set(Object obj, object value) 将参数对象obj中此Field对象表示成员变量的数值修改为参数value的数值
void setAccessible(boolean flag) 当实参传递true时,则反射对象在使用时应该取消Java语言访问检查
int getModifiers() 获取成员变量的访问修饰符
Class<?> getType() 获取成员变量的数据类型
String getName() 获取成员变量的名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class FieldTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
/*使用原始方式来构造对象以及获取成员变量的数值并打印
Person p1 = new Person("zhangfei");
System.out.println("获取到的成员变量数值为:" + p1.name);*/
//使用反射机制来构造对象以及获取成员变量的数值并打印
//获取Class对象
Class aClass = Class.forName("com.example.qy161_backstage.reflex.Person");
//根据Class对象获取对应的有参构造方法
Constructor constructor = aClass.getConstructor(String.class);
//使用有参构造方法来得到Person类型的对象
Object name = constructor.newInstance("name");
//根据Class对象获取对应的成员变量信息
Field declaredField = aClass.getDeclaredField("name");
/* 设置Java语言访问检查的取消 暴力反射 */
declaredField.setAccessible(true);
//使用Person类型的对象来获取成员变量的数值并打印
System.out.println("获取到的成员变量数值为:" + declaredField.get(name));
//使用原始方式修改指定对象中成员变量的数值后再次打印
//p1.name = "guanyu";
//System.out.println("修改后成员变量的数值为:" + p1.name);
//使用反射机制修改指定对象中成员变量的数值后再次打印
declaredField.set(name,"zhangfei");
System.out.println(declaredField.get(name));
System.out.println("======================");
//获取Class对象对应类中所有的成员变量
Field[] declaredField1 = aClass.getDeclaredFields();
for (Field d: declaredField1) {
System.out.println("获取到的访问修饰符为:" + d.getModifiers());
System.out.println("获取到的数据类型为:" + d.getType());
System.out.println("获取到的成员变量名称是:" + d.getName());
}

}
}

Method类

基本概念:java.lang.reflect.Method类主要用于描述获取到的单个成员方法信息

获取到Method类的方法

方法声明 功能介绍
Method getMethod(String name,Class<?>… parameterTypes) 用于获取该Class对象表示类中名字为name参数为parameterTypes的指定公共成员方法
MethodgetMethods() 用于获取该Class对象表示类中所有公共成员方法

Method类的常用方法

方法声明 功能介绍
object invoke(Object obj,Object… args) 使用对象obj来调用此Method对象所表示的成员方法,实参传递args
int getModifiers() 获取方法的访问修饰符
Class<?> getReturnType() 获取方法的返回值类型
String getName() 获取方法的名称
Class<?>getParameterTypes() 获取方法所有参数的类型
Class<?>-getExceptionTypes() 获取方法的异常信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class MethodTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//使用反射机制构造对象并调用方法打印结果
Class c1 = Class.forName("com.example.qy161_backstage.reflex.Person");
//根据Class对象来获取对应的有参构造方法
Constructor constructor = c1.getConstructor(String.class);
//使用有参构造方法构造对象并记录
Object object = constructor.newInstance("zhangfei");
//根据Class对象来获取对应的成员方法
Method method = c1.getMethod("getName");
//使用对象调用成员方法进行打印
System.out.println("调用方法的返回值是:" + method.invoke(object));
//使用反射机制来获取类中的所有成员方法并打印
Method[] methods = c1.getMethods();
for (Method mt : methods) {
System.out.println("成员方法的修饰符是:" + mt.getModifiers());
System.out.println("成员方法的返回值类型是:" + mt.getReturnType());
System.out.println("成员方法的名称是:" + mt.getName());
System.out.println("成员方法形参列表的类型是:");
Class<?>[] parameterTypes = mt.getParameterTypes();
for (Class ct : parameterTypes) {
System.out.print(ct + " ");
}
System.out.println("成员方法的异常类型列表是:");
Class<?>[] exceptionTypes = mt.getExceptionTypes();
for (Class ct: exceptionTypes) {
System.out.print(ct + " ");
}
}

}
}

获取其它结构信息

方法声明 功能介绍
Package getPackage() 获取所在的包信息
Class<? super T> getSuperclass() 获取继承的父类信息
Class<?>[] getInterfaces() 获取实现的所有接口
AnnotationgetAnnotations() 获取注解信息
TypegetGenericInterfaces() 获取泛型信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Person {
private String name;
private int age;
public Person() {}

public Person(String name) {
this.name = name;
}
public Person(String name,int age) {
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;
}

@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1
2
3
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
1
2
3
4
5
6
7
8
@MyAnnotation
public class Student <T,E> extends Person implements Comparable, Serializable {

@Override
public int compareTo(Object o) {
return 0;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class StudentTest {
public static void main(String[] args) throws ClassNotFoundException {
// 获取Student类型的Class对象
Class c1 = Class.forName("com.example.qy161_backstage.reflex.Student");
System.out.println("获取到的包信息是:" + c1.getPackage());
System.out.println("获取到的父类信息是:" + c1.getSuperclass());
System.out.println("获取到的接口信息是:");
Class[] interfaces = c1.getInterfaces();
for (Class ct : interfaces) {
System.out.print(ct + " ");
}
System.out.println();
System.out.println("获取到的注解信息是:");
Annotation[] annotations = c1.getAnnotations();
for (Annotation at : annotations) {
System.out.print(at + " ");
}
System.out.println();
System.out.println("获取到的泛型信息是:");
Type[] genericInterfaces = c1.getGenericInterfaces();
for (Type tt : genericInterfaces) {
System.out.print(tt + " ");
}
System.out.println();
}
}