1.反射概述
package com.yl.pdfdemo.day08.p6;
import org.junit.Test;
import java.lang.annotation.ElementType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Author wfj
* @Date 2021/7/2
* @Description 反射
* @Version 1.0
*/
public class ReflectionTest {
/**
* 反射:被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,
* 并且能操作任意对象的内部属性和方法
*
* 关于java.lang.Class类的理解
*
* 1.类的加载过程
* 程序经过javac.exe命令以后,会生成一个或者多个字节码文件(.class结尾)
* 接着我们使用java.exe命令对某个字节码文件解析运行,相当于将某个字节码文件加载到内存中。
* 此过程称为类的加载,加载到内存中的类,我们称之为运行时类,此运行时类就作为Class的一个实例
*
* 2.换句话说,Class的实例就对应着一个运行时类
*/
//反射之前对于Animal的创建
@Test
public void test1() {
Animal animal = new Animal("xiaobai",13);
animal.show();
//在Animal类外部,不可以调用其内部的私有的属性,构造器,方法
//Animal animal1 = new Animal("小白");
}
//有了反射后,对Aniaml的操作
@Test
public void test2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//获取类对象
Class clazz = Animal.class;
//1.通过反射构造对象
//方式一
Constructor constructor = clazz.getConstructor(String.class, int.class);
Object object = constructor.newInstance("小黑",12);
Animal animal = (Animal) object;
System.out.println(animal.toString());//Animal{name='小黑', age=12}
//方式二
//newInstance(),调用了运行时类的空参构造器,所以类一般都要提供空参构造器,并且是public的
Animal a1 = (Animal)clazz.newInstance();
System.out.println(a1); //Animal{name='null', age=0}
//2.通过反射,调用指定的属性或方法
Field age = clazz.getDeclaredField("age");
age.set(animal,11);
System.out.println(animal.toString()); //Animal{name='小黑', age=11}
//调用方法
Method show = clazz.getDeclaredMethod("show");
show.invoke(animal);
Method show1 = clazz.getDeclaredMethod("showType",String.class);
show1.invoke(animal,"治愈系");
//注意:通过反射可以获取Animal类的私有结构:属性,方法,构造器
//调用私有构造器
Constructor constructor1 = clazz.getDeclaredConstructor(String.class);
constructor1.setAccessible(true);
Animal animal1 = (Animal) constructor1.newInstance("小紫");
System.out.println(animal1.toString()); // Animal{name='小紫', age=0}
//调用私有属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(animal1,"大桥");
System.out.println(animal1.toString());// Animal{name='大桥', age=0}
//调用私有方法
Method method = clazz.getDeclaredMethod("showAgeAndName", int.class, String.class);
method.setAccessible(true);
String str = (String)method.invoke(animal1,18,"xiu");
System.out.println(str); // age=18and name = xiu
}
//获取Class实例的方式
@Test
public void test3() throws ClassNotFoundException {
//方式一:调用运行时类的属性.class
Class clazz1 = Animal.class;
System.out.println(clazz1);//class com.yl.pdfdemo.day08.p6.Animal
//方式二:通过运行时类的对象
Animal animal = new Animal();
Class clazz2 = animal.getClass();
System.out.println(clazz2);//class com.yl.pdfdemo.day08.p6.Animal
//方式三:调用Class的静态方法,forName(String classPath)
Class clazz3 = Class.forName("com.yl.pdfdemo.day08.p6.Animal");
System.out.println(clazz3);//class com.yl.pdfdemo.day08.p6.Animal
System.out.println(clazz1 == clazz2); //true
System.out.println(clazz1 == clazz3); //true
//方式四:使用类的加载器
ClassLoader classLoader = ReflectionTest.class.getClassLoader();
Class clazz4 = classLoader.loadClass("com.yl.pdfdemo.day08.p6.Animal");
System.out.println(clazz4); //class com.yl.pdfdemo.day08.p6.Animal
}
//Class实例可以是哪些结构?接口,基本数据类型,普通类,注解,枚举,数组,接口,void等
@Test
public void test4() {
Class clazz1 = Object.class;
Class clazz2 = Comparable.class;
Class clazz3 = int.class;
Class clazz4 = String[].class;
Class clazz5 = ElementType.class;
Class clazz6 = Override.class;
Class clazz7 = int[][].class;
Class clazz8 = void.class;
Class clazz9 = Class.class;
//只要数组的元素类型和维度一样,就是同一个Class
int[] a = new int[10];
int[] b = new int[100];
Class clazz10 = a.getClass();
Class clazz11 = b.getClass();
System.out.println(clazz10 == clazz11); //true
}
}
package com.yl.pdfdemo.day08.p6;
/**
* @Author wfj
* @Date 2021/7/2
* @Description
* @Version 1.0
*/
public class Animal {
private String name;
public int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
private Animal(String name) {
this.name = name;
}
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 void show() {
System.out.println("ANIMAL...");
}
public String showType(String type) {
System.out.println(type);
return type;
}
private String showAgeAndName(int age,String name) {
System.out.println("age="+age+"and name = "+name);
return "age=" + age + "and name = "+ name;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.用到的测试的文件
1)Creature类
package com.yl.pdfdemo.day08.p6;
import java.io.Serializable;
/**
* @Author wfj
* @Date 2021/7/2
* @Description
* @Version 1.0
*/
public class Creature<T> implements Serializable {
private char gender;
public double weight;
private void breath() {
System.out.println("creature breath...");
}
public void eat() {
System.out.println("creature eat...");
}
}
2)Person类
package com.yl.pdfdemo.day08.p6;
import java.io.IOException;
/**
* @Author wfj
* @Date 2021/7/2
* @Description
* @Version 1.0
*/
@MyAnnotation(value = "p")
public class Person extends Creature<String> implements Comparable<String>,MyInterface {
private String name;
int age;
public int id;
private static String gender;
public Person() {
}
@MyAnnotation(value = "abc")
private Person(String name) {
this.name = name;
}
Person(String name,int age) {
this.name = name;
this.age = age;
}
@MyAnnotation
private String show(String national) {
System.out.println("国籍为:"+national);
return national;
}
public String display(String str) throws IOException,NullPointerException {
return str;
}
@Override
public void info() {
System.out.println("Person info...");
}
@Override
public int compareTo(String o) {
return 0;
}
private static void print() {
System.out.println("static method");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
3)MyAnnotation
package com.yl.pdfdemo.day08.p6;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
/**
* @Author wfj
* @Date 2021/7/2
* @Description
* @Version 1.0
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "hello vue";
}
4)MyInterface
package com.yl.pdfdemo.day08.p6;
/**
* @Author wfj
* @Date 2021/7/2
* @Description
* @Version 1.0
*/
public interface MyInterface {
void info();
}
3.获取运行时类的结构
package com.yl.pdfdemo.day08.p6;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
/**
* @Author wfj
* @Date 2021/7/2
* @Description 通过反射获取运行时类的结构
* @Version 1.0
*/
public class test {
//获取当前运行时类的属性
@Test
public void test1() {
Class clazz1 = Person.class;
//getFields():获取当前运行时类及其父类中声明为public的属性
Field[] fields1 = clazz1.getFields();
for (Field field : fields1) {
System.out.println(field);
}
System.out.println("============");
//getDeclaredFields():获取当前运行时类的所有属性,不包含父类中声明的属性
Field[] fields2 = clazz1.getDeclaredFields();
for (Field field : fields2) {
System.out.println(field);
}
//除此之外,还可以获取权限修饰符,数据类型,变量名
Field[] fields3 = clazz1.getDeclaredFields();
for (Field field : fields3) {
//权限修饰符
int modeifier = field.getModifiers();
System.out.print(Modifier.toString(modeifier) + "\t");
//数据类型
Class type = field.getType();
System.out.print(type.getName() + "\t");
//变量名
String name = field.getName();
System.out.print(name);
System.out.println();
}
//以上输出结果
/**
* private java.lang.String name
* int age
* public int id
*/
}
//获取运行时类的方法的结构
@Test
public void test2() {
Class clazz = Person.class;
//getMethods() 获取当前运行时类及其所有父类中声明为public的方法
Method[] methods1 = clazz.getMethods();
for (Method method : methods1) {
System.out.println(method);
}
//getMethods() 获取当前运行时类的所有父方法,不包含父类的方法
Method[] methods2= clazz.getDeclaredMethods();
for (Method method : methods2) {
System.out.println(method);
}
System.out.println("=================");
//获取方法的权限修饰符,返回值类型,注解,方法名等等
Method[] methods3= clazz.getDeclaredMethods();
for (Method method : methods3) {
//获取方法上的注解
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获取权限修饰符
System.out.print(Modifier.toString(method.getModifiers()) + "\t");
//获取方法返回值类型
System.out.print(method.getReturnType().getName() + "\t");
//获取方法名
System.out.print(method.getName() + "\t");
System.out.print("(");
//获取形参列表
Class[] parameterTypes = method.getParameterTypes();
if(!(parameterTypes == null && parameterTypes.length == 0)) {
for (int i = 0; i < parameterTypes.length; i++) {
if (i == parameterTypes.length-1) {
System.out.print(parameterTypes[i].getName());
break;
}
System.out.print(parameterTypes[i].getName() + ",");
}
}
System.out.print(")");
//获取抛出的异常
Class[] exceptionTypes = method.getExceptionTypes();
if (!(exceptionTypes == null && exceptionTypes.length == 0)) {
System.out.print("throw");
for (int i = 0; i < exceptionTypes.length; i++) {
if (i == exceptionTypes.length - 1) {
System.out.print(exceptionTypes[i].getName());
break;
}
System.out.println(exceptionTypes[i].getName() + ",");
}
}
System.out.println();
//结果
/**
* public int compareTo (java.lang.String)throw
* public volatile int compareTo (java.lang.Object)throw
* public void info ()throw
* @com.yl.pdfdemo.day08.p6.MyAnnotation(value=hello vue)
* private java.lang.String show (java.lang.String)throw
* public java.lang.String display (java.lang.String)throwjava.io.IOException,
*/
}
}
//获取构造器结构
@Test
public void test3 () {
Class clazz = Person.class;
//getConstructors(): 获取当前运行时类声明为public的构造器
Constructor[] constructors = clazz.getConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
//getDeclaredConstructors(): 获取当前运行时类所有的构造器
Constructor[] constructors1 = clazz.getDeclaredConstructors();
for (Constructor c : constructors1) {
System.out.println(c);
}
}
//获取运行时类的父类
@Test
public void test4() {
Class clazz = Person.class;
Class superclass = clazz.getSuperclass();
System.out.println(superclass);//class com.yl.pdfdemo.day08.p6.Creature
}
//获取运行时类帶泛型的父类
@Test
public void test5() {
Class clazz = Person.class;
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println(genericSuperclass);//com.yl.pdfdemo.day08.p6.Creature<java.lang.String>
//获取泛型类型
ParameterizedType paramType = (ParameterizedType)genericSuperclass;
Type[] arguments = paramType.getActualTypeArguments();
System.out.println(((Class)arguments[0]).getName());//java.lang.String
}
//获取运行时类实现的接口
@Test
public void test6() {
Class clazz = Person.class;
Class[] interfaces = clazz.getInterfaces();
for (Class c : interfaces) {
System.out.println(c);
}
System.out.println();
//获取运行时父类实现的接口
Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
for (Class c : interfaces1) {
System.out.println(c);
}
}
//获取当前运行时类所在的包
@Test
public void test7() {
Class clazz = Person.class;
Package aPackage = clazz.getPackage();
System.out.println(aPackage); //package com.yl.pdfdemo.day08.p6
}
//获取运行时类声明的注解
@Test
public void test8() {
Class clazz = Person.class;
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation); //@com.yl.pdfdemo.day08.p6.MyAnnotation(value=p)
}
}
}
4.调用运行时类的结构
package com.yl.pdfdemo.day08.p6;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @Author wfj
* @Date 2021/7/13
* @Description
* @Version 1.0
*/
public class test1 {
@Test
public void test1() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
Class clazz = Person.class;
//创建对象
Person person = (Person) clazz.newInstance();
//获取指定属性
//要求声明的属性为public的,通常不用这种方式
Field id = clazz.getField("id");
//设置值
id.set(person,1000);
//获取某个对象当前属性的值
int i = (int)id.get(person);
System.out.println(i);
}
//操作运行时类的属性
@Test
public void test2() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
Class clazz = Person.class;
Person person = (Person) clazz.newInstance();
//获取指定属性
Field name = clazz.getDeclaredField("name");
//设置当前属性可以访问
name.setAccessible(true);
//设置值
name.set(person,"yang");
System.out.println(name.get(person)); // yang
//获取静态属性,设置值,取值
Field gender = clazz.getDeclaredField("gender");
gender.setAccessible(true);
gender.set(null,"男");
System.out.println(gender.get(null)); //男
}
//操作运行时类的方法
@Test
public void test3() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class clazz = Person.class;
Person person = (Person) clazz.newInstance();
//获取指定的方法
Method show = clazz.getDeclaredMethod("show", String.class);
show.setAccessible(true);
//调用方法
String vue = (String)show.invoke(person, "vue");
System.out.println(vue);
System.out.println("=============");
//调用静态方法
Method print = clazz.getDeclaredMethod("print");
print.setAccessible(true);
//调用静态方法,第一个参数为Class对象
Object o = print.invoke(Person.class);
//或者
//Object o = print.invoke(null);
//如果方法没有返回值会返回null
System.out.println(o);// null
}
//调用运行时类的构造器
@Test
public void test4() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = Person.class;
//获取构造器
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//保证此构造器是可以访问的
constructor.setAccessible(true);
//创建对象
Person person = (Person)constructor.newInstance("tom");
System.out.println(person); //Person{name='tom', age=0, id=0}
}
}
5.类加载器额外概述
package com.yl.pdfdemo.day08.p6;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
/**
* @Author wfj
* @Date 2021/7/2
* @Description 类加载器
* @Version 1.0
*/
public class ClassLoaderTest {
@Test
public void test1() {
//对于自定义类,使用系统类加载器进行加载
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
System.out.println(classLoader); // sun.misc.Launcher$AppClassLoader@18b4aac2
//调用系统内加载器的getParent()方法:获取扩展类加载器
ClassLoader classLoader1 = classLoader.getParent();
System.out.println(classLoader1); // sun.misc.Launcher$ExtClassLoader@439f5b3d
//调用扩展类加载的getParent():无法获取引导类加载器
//引导类加载器主要负责加载java核心类库,无法加载自定义类的
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println(classLoader2); // null
ClassLoader classLoader3 = String.class.getClassLoader();
System.out.println(classLoader3); // null
}
/**
* Properties:用来读取配置文件
*/
@Test
public void test2() throws Exception{
Properties pros = new Properties();
//方式一:默认加载路径是当前module下,如果配置文件在src下,需要指定路径
FileInputStream is = new FileInputStream("src\\jdbc.properties");
pros.load(is);
System.out.println(pros.get("userName")); //root
System.out.println(pros.get("password")); //123456
//方式二:通过类的加载器,默认加载路径是src下
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
InputStream is1 = classLoader.getResourceAsStream("jdbc.properties");
pros.load(is1);
System.out.println(pros.get("userName"));// root
System.out.println(pros.get("password")); //123456
}
}