说明:以下演示大量使用F3和Ctrl+T理清继承结构
两种获取方式
Class<? extends Person> ci = Person.class;
@想一想@:为什么是<? extends Person>,说明什么?
//假如有:Class<Person> ciByObject = null; Class<? extends Person> ciByObject = Teacher.class; Person p = ciByObject.newInstance();同一个类型,无论通过何种方式获得的Type对象,其实都是同一个对象:
都可以通过Class对象获得:
Field name = Person.class.getField("name"); //读写字段 name.set(fg, "大飞哥"); System.out.println(name.get(fg));
Method eat = Person.class.getMethod("eat", Double.class); //调用方法 eat.invoke(new Person("飞哥"), 18.6);
Java对其进行了很好的整理(值得借鉴):
PS:Class实现的是interface Type,Type下面还有四个和泛型相关的接口(仅供了解)
所有反射相关的类,都放在两个package里面:
package java.lang; package java.lang.reflect;
以调用私有方法为例:
Method eat =Person.class.getDeclaredMethod("eat"); eat.setAccessible(true); eat.invoke(new Person());
关键:
继承和多态,在反射中仍然起作用。
首先,子类类型信息对象,就直接继承(包含)着她父类成员:
//Teacher中并没有声明eat()方法,eat()来自基类 Teacher.class.getMethod("eat").invoke(new Teacher());
其次,也可以由子类对象调用其父类成员:
//Teacher对象可以调用基类Person的eat()方法 Person.class.getMethod("eat").invoke(new Teacher());
比较复杂一点的是如果子类覆盖(override)了父类方法:
//类似于:new Person().eat(),OK Person.class.getMethod("eat").invoke(new Person()); //类似于:new Teacher().eat(),OK Person.class.getMethod("eat").invoke(new Teacher()); //运行时错误:Person对象不能调用Teacher中的eat()方法 Teacher.class.getMethod("eat").invoke(new Person());
我们可以使用@interface自己定义一个注解。
很像一个接口,嗯……,里面还可以有方法声明一样的东东(正式名称attribute:属性),比如:
@interface guru{ //注意这个@符号 int level(); }
这样,标记时就需要指定level的值:
@guru(level = 2) class Person {如果level命名为value的话,value=可以省略,比如:
@Retention(RetentionPolicy.RUNTIME)
标记该注解会在一直保留(retention)到运行时(runtime)
然后,通过AnnotatedElement接口实例(比如:Class<T>/Member/Field)的:
Annotation[] annotations = Person.class.getAnnotations(); for (int i = 0; i < annotations.length; i++) { System.out.println(annotations[i]); }
Guru annotation = Person.class.getAnnotation(Guru.class); System.out.println(annotation.value());
记JDK/JRE中自带的注解,简单分类:
代码用的:
注解用的:
其他:
所以,单个.class文件是可以执行的,但是,项目中通常都会有多个.java源代码文件,编译后就会形成多个.class文件,这时候咋办?
通常我们会把它们打包(package)成.jar(Java Archive)文件,打包实际上包含两个过程:
Main.class.getPackage();
但不能从这个Package中得到所有的类,为啥呢?
JVM 运行并不是一次性加载所需要的全部类的,它是按需加载(又被称之为延迟加载):在程序在运行的过程中,需要用什么类,就加载什么类。
所谓加载,就是把Class 的字节码形式( *.class)转换成内存形式的 Class 对象,这个过程是通过 ClassLoader 来完成的。
F3演示:forName()调用ClassLoader……
演示:eclipse上新建一个JUnit项目
官方定义JUnit5由三部分组成:
尝试着理解:Platform定义接口(API),所以是开放的
测试方法:
测试环境:
断点演示:执行顺序
多快好省!前端后端,线上线下,名师精讲
更多了解 加: