1.类的加载器以及如何获取Class的实例
public class TestReflection {
//关于类的加载器:ClassLoader
@Test
public void test5() throws Exception{
ClassLoader loader1 = ClassLoader.getSystemClassLoader();//获取系统类加载器
System.out.println(loader1);
ClassLoader loader2 = loader1.getParent();//获取扩展类加载器
System.out.println(loader2);
ClassLoader loader3 = loader2.getParent();//引导类加载器无法被获取
System.out.println(loader3);
Class class1 = Person.class;
ClassLoader loader4 = class1.getClassLoader();
System.out.println(loader4);
String className = "java.lang.Object";
Class class2 = Class.forName(className);
ClassLoader loader5 = class2.getClassLoader();//引导类加载器无法被获取
System.out.println(loader5);
ClassLoader loader = this.getClass().getClassLoader();
InputStream is = loader.getResourceAsStream("com\\panda\\java\\jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String name = pros.getProperty("user");
System.out.println(name);
String password = pros.getProperty("password");
System.out.println(password);
}
//如何获取Class的实例(3种)
@Test
public void test4() throws ClassNotFoundException{
//1.调用运行时类本身的.class属性
Class class1 = Person.class;
System.out.println(class1.getName());
Class class2 = String.class;
System.out.println(class2.getName());
//2.通过运行时类的对象获取
Person person = new Person();
Class class3 = person.getClass();
System.out.println(class3.getName());
//3.通过Class的静态方法获取
String className = "com.panda.java.Person";
Class class4 = Class.forName(className);
System.out.println(class4.getName());
//4.通过类的加载器
ClassLoader classLoader = this.getClass().getClassLoader();
Class class5 = classLoader.loadClass(className);
System.out.println(class5.getName());
}
/*
* java.lang.class:是反射的源头
* 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)
* 此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
* 1.每一个运行时类只加载一次!
* 2.有了Class的实例以后,我们才可以进行如下的操作:
* 1)*创建对应的运行时类的对象
* 2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)
* 3)*调用对应的运行时类的指定的结构(属性、方法、构造器)
* 4)反射的应用:动态代理
*/
@Test
public void test3(){
Person person = new Person();
Class class1 = person.getClass();//通过运行时类的对象,调用其getClass(),返回其运行时类
System.out.println(class1);
}
//有了反射,可以通过反射创建一个类的对象,并调用其中的结构
@Test
public void test2() throws Exception{
Class class1 = Person.class;
//1.创建class1对应的运行时类Person类的对象
Person person = (Person) class1.newInstance();
//2.通过反射调用运行时类的指定的属性
Field f1 = class1.getField("name");
f1.set(person, "liuDeHua");
System.out.println(person);
Field f2 = class1.getDeclaredField("age");
f2.setAccessible(true);
f2.set(person, 20);
System.out.println(person);
//3.通过反射调用运行时类的指定的方法
Method m1 = class1.getMethod("show");
m1.invoke(person);
Method m2 = class1.getMethod("display", String.class);
m2.invoke(person, "CHN");
}
//在有反射以前,如何创建一个类的对象,并调用其中的方法、属性
@Test
public void test1(){
Person person = new Person();
person.setAge(10);
person.setName("liming");
System.out.println(person);
person.show();
//person.display("中国");
}
}
2.通过反射获取对应的运行时类的属性
public class TestField {
//获取对应的运行时类的属性
@Test
public void test1(){
Class class1 = Person.class;
//1.getFields(),只能获取到运行时类中极其父类中声明为public的属性
Field[] fields = class1.getFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
System.out.println();
//2.getDeclaredFields(),获取运行时类本身声明的所有的属性
Field[] fields2 = class1.getDeclaredFields();
for(Field f : fields2){
System.out.println(f.getName());
}
}
/*
* 权限修饰符 变量类型 变量名
* 获取属性的各个部分的内容
*/
@Test
public void test2(){
Class class1 = Person.class;
Field[] fields2 = class1.getDeclaredFields();
for(Field f : fields2){
//1.获取每个属性的权限修饰符
int i = f.getModifiers();
String str = Modifier.toString(i);
System.out.print(str + " ");
//2.获取属性的变量类型
Class type = f.getType();
System.out.print(type.getName() + " ");
//3.获取属性名
System.out.print(f.getName());
System.out.println();
}
}
//调用运行时类指定的属性
@Test
public void test3() throws Exception, SecurityException{
Class class1 = Person.class;
//1.获取指定的属性
//getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性
Field name = class1.getField("name");
//2.创建运行时类的对象
Person person = (Person) class1.newInstance();
//3.将运行时类的指定的属性赋值
name.set(person, "Jack");
System.out.println(person);
System.out.println();
//getDeclaredField(String fieldName):获取运行时类中指定属性名为fieldName的属性
Field age = class1.getDeclaredField("age");
//由于属性权限修饰的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作
age.setAccessible(true);
age.set(person, 22);
System.out.println(person);
}
}
3.通过反射获取运行时类的方法
public class TestMethod {
//1.获取运行时类的方法
@Test
public void test1(){
Class class1 = Person.class;
//1.getMethods(),获取运行时类及其父类中所有的声明为public的方法
Method[] methods = class1.getMethods();
for(Method m : methods){
System.out.println(m);
}
System.out.println();
//2.getDeclaredMethods(),获取运行时类本身声明的所有的方法
Method[] methods2 = class1.getDeclaredMethods();
for(Method m : methods2){
System.out.println(m);
}
}
//注解 权限修饰符 返回值类型 方法名 形参列表 异常
@Test
public void test2(){
Class class1 = Person.class;
Method[] methods2 = class1.getDeclaredMethods();
for(Method m : methods2){
//1.注解
Annotation[] ann = m.getAnnotations();
for(Annotation a : ann){
System.out.println(a);
}
//2.权限修饰符
String str = Modifier.toString(m.getModifiers());
System.out.print(str + " ");
//3.返回值类型
Class returnType = m.getReturnType();
System.out.print(returnType.getName() + " ");
//4.方法名
System.out.print(m.getName() + " ");
//5.形参列表
System.out.print("(");
Class[] params = m.getParameterTypes();
for(Class p : params){
System.out.print(p.getName() + " ");
}
System.out.print(")");
//6.异常类型
Class[] exps = m.getExceptionTypes();
for (int i = 0; i < exps.length; i++) {
System.out.println(exps[i].getName());
}
System.out.println();
}
}
//调用运行时类中的指定的方法
@Test
public void test3() throws Exception{
Class class1 = Person.class;
//getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法
Method m1 = class1.getMethod("show");
Person person = (Person) class1.newInstance();
//调用指定的方法:Object invoke(Object obj,Object ... obj)
Object returnVal = m1.invoke(person);//我是一个人
System.out.println(returnVal);//null
Method m2 = class1.getMethod("toString");
Object returnVal1 = m2.invoke(person);
System.out.println(returnVal1);//Person [name=null,age=0]
//对于运行时类中静态方法的调用
Method m3 = class1.getMethod("info");
m3.invoke(Person.class);//中国人
//getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法
Method m4 = class1.getDeclaredMethod("display",String.class);
m4.setAccessible(true);
Object value = m4.invoke(person,"CHN");//我的国籍是:CHN
}
}
4.通过反射调用指定的构造器
public class TestConstructor {
@Test
public void test1() throws Exception{
String className = "com.panda.java.Person";
Class class1 = Class.forName(className);
//创建对应的运行时类的对象.使用newInstan(),实际上就是调用了运行时类的空参的构造器
//要想能创建成功:1.要求对应的运行时类要有空参的构造器。2.构造器的权限修饰符的权限要足够
Object object = class1.newInstance();
Person person = (Person) object;
System.out.println(person);
}
@Test
public void test2() throws ClassNotFoundException{
String className = "com.panda.java.Person";
Class class1 = Class.forName(className);
Constructor[] cons = class1.getDeclaredConstructors();
for(Constructor constructor : cons){
System.out.println(constructor);
}
}
//调用指定的构造器,创建运行时类的对象
@Test
public void test3() throws Exception{
String className = "com.panda.java.Person";
Class class1 = Class.forName(className);
Constructor constructor = class1.getDeclaredConstructor(String.class,int.class);
constructor.setAccessible(true);
Person person = (Person) constructor.newInstance("李明",21);
System.out.println(person);
}
}
5.通过反射获取其他public class TestOthers {
//1.获取运行时类的父类
@Test
public void test1(){
Class class1 = Person.class;
Class supercClass = class1.getSuperclass();
System.out.println(supercClass);
}
//2.获取带泛型的父类
@Test
public void test2(){
Class class1 = Person.class;
Type type = class1.getGenericSuperclass();
System.out.println(type);
}
//3.获取父类的泛型
@Test
public void test3(){
Class class1 = Person.class;
Type type = class1.getGenericSuperclass();
ParameterizedType pType = (ParameterizedType) type;
Type[] ars = pType.getActualTypeArguments();
System.out.println(((Class)ars[0]).getName());
}
//4.获取实现的接口
@Test
public void test4(){
Class class1 = Person.class;
Class[] interfaces = class1.getInterfaces();
for(Class c : interfaces){
System.out.println(c);
}
}
//5.获取所在的包
@Test
public void test5(){
Class class1 = Person.class;
Package package1 = class1.getPackage();
System.out.println(package1);
}
//6.获取注解
@Test
public void test6(){
Class class1 = Person.class;
Annotation[] anns = class1.getAnnotations();
for(Annotation annotation : anns){
System.out.println(annotation);
}
}
}
附录:
1.父类Creature
public class Creature<T> {
public double weight;
public void breath(){
System.out.println("呼吸!");
}
}
2.Person类
@MyAnnotation(value = "panda")
public class Person extends Creature<String> implements Comparable,MyInterface{
public String name;
private int age;
int id;
public Person() {
super();
}
public Person(String name) {
super();
this.name = name;
}
public Person(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;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@MyAnnotation(value = "abc123")
public void show(){
System.out.println("我是一个人");
}
private void display(String nation)throws Exception{
System.out.println("我的国籍是:" + nation);
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
public static void info(){
System.out.println("中国人!");
}
class Bird{
}
}
3.注解类
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
4.接口类
public interface MyInterface extends Serializable{
}
5.jdbc.properties文件
user=root
password=123456