注解与反射机制

注解与反射机制

一、注解

1.什么是注解

java.annotation包
Annotation是从JDK1.5开始引入的新技术,注解即可以对程序员解释又可以对程序解释

2.注解与注释的区别

注释:对程序员解释代码信息

注解:对程序和程序员解释代码信息

3.注解的所用

不是程序本身,可以对程序作出解释(与注释(comment)类似)

可以被其他程序(编译器)读取

4.注解的格式

注解是以“@注释名”在代码中存在的,还可以添加一些参数

例如:@SuppressWarnings(value=“unchecked”)

5.注解的应用

可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制实现对这些数据的访问

6.内置注解

@Overrlde:定义在java.lang.Override中,此注解只适用于修饰方法,表示一个方法声明打算重写超类中的另一个方法声明

@Deprecated:定义在java.lang.Deprecated中.此注解可以用于修饰方法,属性,类。表示不鼓励使用这样的元素.通常是因为它很危险或者存在更好的选择

@SuppressWarnings:镇压警告,定义在java.lang.SuppressWarnings中用来抑制编译时的警告信息,与前两个注释有所不同.你需要添加参数才能正确使用。这些参数都是已经定义好了的.我们选择性的使用就好了
@SuppressWarnings(“all”)抑制所有类型的警告信息
@SuppressWarnings(“unchecked”)抑制单类型的警告信息
@SuppressWarnings(value={“unchecked”,“deprecation”})抑制多类型的警告信息

7.元注解

元注解的作用:负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明

这些类型和它们所支持的类在java.lang.annotation包中可以找到

(@Target,@Retention,@Documented,@Inherited )

@Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

@Retention:表示需要要在什么级别保存该注择信息,用于描述注解的生命周期

(SOURCE < CLASS <RUNTIME)

@Document:说明该注解将被包含在javadoc中

@lnherited:说明子类可以继承父类中的该注解

@MyAnnotation02
public class Test01<@MyAnnotation02 T> {

	@MyAnnotation02
	public String name;
	
	@MyAnnotation02
	public Test01() {
	}
	
	@MyAnnotation01
	@MyAnnotation02
	@MyAnnotation03("aaa")
	@MyAnnotation04
	@MyAnnotation05(name = "aaa")
	@MyAnnotation06(names = {"aaa","bbb"})
	@MyAnnotation07(names={"aaa","bbb"},username="撕裂的忧伤")
	public void method(String str){
		
		@MyAnnotation02
		int i = 100;
		System.out.println(i);
	}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 该注解只能在方法上使用,并且没有参数
 */

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation01 {

}
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 该注解可以在方法、类、构造方法、属性、局部变量、泛型上使用,并且没有参数
 */

@Target({METHOD,TYPE,CONSTRUCTOR,FIELD,LOCAL_VARIABLE,TYPE_PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation02 {

}

import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 该注解可以在方法上使用,并且有一个参数
 */
@Target(METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation03 {

	String value();
}
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 该注解可以在方法上使用,并且有一个参数
 */
@Target(METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation04 {

	String value() default "abc";//设置默认值
}
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 该注解可以在方法上使用,并且有一个参数
 */
@Target(METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation05 {

	String name();
}
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 该注解可以在方法上使用,并且有一个参数
 */
@Target(METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation06 {

	String[] names();
}
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 该注解可以在方法上使用,并且有一个参数
 */
@Target(METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation07 {

	String[] names();
	String username();
	String password() default "00000000";
}

8.自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口

分析:

@interface用来声明一个注解,格式:public @interface注解名{定义内容}

其中的每一个方法实际上是声明了一个配置参数.

方法的名称就是参数的名称.

返回值类型就是参数的类型(返回值只能是基本类型、Class、String、enum)

可以通过default来声明参数的默认值

如果只有一个参数成员,一般参数名为value()

注解元素必須要有值,我们定义注解元素时,经常使用空字符串.0作为默认值

import java.util.ArrayList;

public class test01 {

	//重写的注解
	@Override
	public boolean equals(Object obj) {
		return super.equals(obj);
	}
	
	//过时的注解
	@Deprecated
	public void method01(){}
	
	//镇压警告的注解
	@SuppressWarnings("all")
	public void method02(){
		ArrayList list = new ArrayList();
		list.add(134);
		list.add("abc");
	}
}

二、反射机制

1.含义:

使用到一个类,该类的class文件会加载到方法区,并且在堆中创建该类的class对象,class对象作为class文件的访问入口,反射就是获取class对象,拿到class对象就可以访问class文件(换言之,可以对该类为所欲为-属性、构造方法、方法)

public class Student extends Person{
	
	private String classId;
	private String id;
	
	public Student() {
	}
	
//	private Student(String classId, String id) {
//		this.classId = classId;
//		this.id = id;
//	}

	public Student(String name, char sex, int age, String classId, String id) {
		super(name, sex, age);
		this.classId = classId;
		this.id = id;
	}

	public String getClassId() {
		return classId;
	}

	public void setClassId(String classId) {
		this.classId = classId;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return "Student [classId=" + classId + ", id=" + id + ", getName()=" + getName() + ", getSex()=" + getSex()
				+ ", getAge()=" + getAge() + "]";
	}
	
//	private String method01(String str){
//		System.out.println("私有的方法 :" + str);
//		return "用良心做教育";
//	}
	
	public static void method02(){
		System.out.println("静态的方法");
	}
}
public class Person {

	private String name;
	private char sex;
	private int age;
	
	public Person() {
	}

	public Person(String name, char sex, int age) {
		this.name = name;
		this.sex = sex;
		this.age = age;
	}

	public String getName() {
		return name;
	}

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

	public char getSex() {
		return sex;
	}

	public void setSex(char sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

//反射工具类
public class ReflexUtil {

	//获取该类及其父类所有的属性对象
	public static List<Field> getAllField(Class<?> clazz){

		List<Field> list = new ArrayList<>();

		for (Class<?> c = clazz;c != null;c = c.getSuperclass()) {
			Field[] fields = c.getDeclaredFields();
			Collections.addAll(list, fields);
		}

		return list;
	}

	//获取该类及其父类指定的属性对象
	public static Field getField(Class<?> clazz,String fieldName){
		for (Class<?> c = clazz;c != null;c = c.getSuperclass()) {
			try {
				Field field = c.getDeclaredField(fieldName);
				return field;
			} catch (NoSuchFieldException e) {//如果该类中找不到属性就会出现该异常
			} 
		}
		return null;
	}

	//设置对象中的属性
	public static void setField(Object obj,String fieldName,Object value){

		Field field = getField(obj.getClass(), fieldName);
		field.setAccessible(true);
		try {
			field.set(obj, value);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}

	//获取该类及其父类所有的构造对象
	public static List<Constructor<?>> getAllConstructor(Class<?> clazz){

		List<Constructor<?>> list = new ArrayList<>();

		for (Class<?> c = clazz;c != null;c = c.getSuperclass()) {
			Constructor<?>[] constructors = c.getDeclaredConstructors();
			Collections.addAll(list, constructors);
		}

		return list;
	}

	//创建该类的对象
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] values){

		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T t = constructor.newInstance(values);
			return t;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return null;
	}

	//获取该类及其父类所有的方法对象
	public static List<Method> getAllMethod(Class<?> clazz){

		List<Method> list = new ArrayList<>();

		for (Class<?> c = clazz;c != null;c = c.getSuperclass()) {
			Method[] methods = c.getDeclaredMethods();
			Collections.addAll(list, methods);
		}

		return list;
	}

	//获取指定的方法对象
	public static Method getMethod(Class<?> clazz,String methodName,Class<?>... parameterTypes){
		for(Class<?> c = clazz;c != null;c = c.getSuperclass() ){
			try {
				Method method = c.getDeclaredMethod(methodName, parameterTypes);
				return method;
			} catch (NoSuchMethodException e) {
			} 
		}
		return null;
	}

	//调用成员方法
	public static Object invoke(Object obj,String methodName,Class<?>[] parameterTypes,Object[] values){
		Method method = getMethod(obj.getClass(), methodName, parameterTypes);
		method.setAccessible(true);
		try {
			Object invoke = method.invoke(obj, values);
			return invoke;
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	//调用静态方法
	public static Object invoke(Class<?> clazz,String methodName,Class<?>[] parameterTypes,Object[] values){
		Method method = getMethod(clazz, methodName, parameterTypes);
		method.setAccessible(true);
		try {
			Object invoke = method.invoke(null, values);//静态方法直接填null,因为不需要对象去调用
			return invoke;
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}
}

2.利用反射获取class对象

方案一
public class Test01 {

	public static void main(String[] args) throws ClassNotFoundException {
		
		//方式1:通过该类的对象获取class对象
		Student stu = new Student();
		Class<? extends Student> class1 = stu.getClass();
		
		//方式2:通过类名获取class对象
		Class<? extends Student> class2 = Student.class;
		
		//方式3:通过Class类的静态方法forName加上类的全路径获取class对象
		Class<?> class3 = Class.forName("com.gl.reflex01.Student");
		
		System.out.println(class1 == class2);//true
		System.out.println(class2 == class3);//true
	}
}
方案二
import java.io.IOException;
import java.util.Properties;

public class Test02 {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		Properties p = new Properties();
		p.load(Test02.class.getClassLoader().getResourceAsStream("classpath.properties"));
		String path = p.getProperty("path");
		
		Class<?> class1 = Class.forName(path);
		System.out.println(class1.getName());
		
	}
}

3.利用反射操作属性 – Field

public class Test03 {

	public static void main(String[] args) throws Exception {
		
//		Properties p = new Properties();
//		p.load(Test03.class.getClassLoader().getResourceAsStream("classpath.properties"));
//		String path = p.getProperty("path");
//		
//		Class<?> clazz = Class.forName(path);
		
		//获取该类和父类的公有的属性对象
//		Field[] fields = clazz.getFields();
//		for (Field field : fields) {
//			System.out.println(field);
//		}
		
		//获取该类所有的属性对象
//		Field[] fields = clazz.getDeclaredFields();
//		for (Field field : fields) {
//			System.out.println(field);
//	  }
		
		//获取该类及其父类所有的属性对象
//		List<Field> fields = ReflexUtil.getAllField(clazz);
//		for (Field field : fields) {
//			System.out.println(field);
//		}
		
		//获取该类指定的公有的属性对象
//		Field field = clazz.getField("classId");
//		System.out.println(field);
		
		//获取该类指定的属性对象
//		Field field = clazz.getDeclaredField("classId");
//		System.out.println(field);
		
		//获取该类及其父类指定的属性对象
//		Field field = ReflexUtil.getField(clazz, "name");
//		System.out.println(field);
		
		//利用反射机制去操作对象中的属性
		
//		Student stu = new Student();
//		Field fieldName = ReflexUtil.getField(clazz, "name");
//		fieldName.setAccessible(true);//设置修改权限
//		fieldName.set(stu, "关羽");
//		System.out.println(stu);
		
		
		//利用反射机制去操作对象中的属性 -- 封装成方法
		Student stu = new Student();
		ReflexUtil.setField(stu, "name", "关羽");
		ReflexUtil.setField(stu, "sex", '男');
		ReflexUtil.setField(stu, "age", 25);
		ReflexUtil.setField(stu, "classId", "2022");
		ReflexUtil.setField(stu, "id", "002");
		System.out.println(stu);
	}
}

4.利用反射操作构造方法

import java.util.Properties;

public class Test04 {

	public static void main(String[] args) throws Exception {
		
		Properties p = new Properties();
		p.load(Test03.class.getClassLoader().getResourceAsStream("classpath.properties"));
		String path = p.getProperty("path");
		
		@SuppressWarnings("unchecked")
		Class<Student> clazz = (Class<Student>) Class.forName(path);
		
		//获取该类公有的构造方法对象
//		Constructor<?>[] constructors = clazz.getConstructors();
//		for (Constructor<?> constructor : constructors) {
//			System.out.println(constructor);
//		}
		
		
		//获取该类所有的构造方法对象
//		Constructor<?>[] constructors = clazz.getDeclaredConstructors();
//		for (Constructor<?> constructor : constructors) {
//			System.out.println(constructor);
//		}
		
		
		//获取该类及其父类所有的构造方法对象
//		List<Constructor<?>> allConstructor = ReflexUtil.getAllConstructor(clazz);
//		for (Constructor<?> constructor : allConstructor) {
//			System.out.println(constructor);
//		}
		
		//获取该类指定的公有的构造方法对象并创建该类对象 -- 无参构造
//		Constructor<?> constructor = clazz.getConstructor();//获取公有的无参构造
//		Student stu = (Student) constructor.newInstance();//利用构造方法对象创建该类的对象
//		System.out.println(stu);
		
		//直接利用无参构造创建对象
//		Student stu = (Student) clazz.newInstance();//底层:获取该类的无参构造对象,并创建该类的对象
//		System.out.println(stu);
		
		//获取该类指定的公有的构造方法对象并创建该类对象 -- 有参构造
//		Constructor<?> constructor = clazz.getConstructor(String.class,char.class,int.class,String.class,String.class);//获取公有的有参构造
//		Student stu = (Student) constructor.newInstance("刘备",'男',23,"2022","001");//利用构造方法对象创建该类的对象
//		System.out.println(stu);
		
		//获取该类指定的构造方法对象并创建该类对象 -- 私有的有参构造
//		Constructor<?> constructor = clazz.getDeclaredConstructor(String.class,String.class);//获取有参构造
//		constructor.setAccessible(true);//设置修改权限
//		Student stu = (Student) constructor.newInstance("2022","001");//利用构造方法对象创建该类的对象
//		System.out.println(stu);
		
		//利用反射机制去创建该类的对象 -- 封装成方法
		Student stu1 = ReflexUtil.newInstance(clazz, null, null);
		System.out.println(stu1);
		Student stu2 = ReflexUtil.newInstance(clazz,new Class[]{String.class,char.class,int.class,String.class,String.class},new Object[]{"刘备",'男',23,"2022","001"});
		System.out.println(stu2);
	}
}

5.利用反射操作方法

import java.util.Properties;

public class Test05 {

	public static void main(String[] args) throws Exception {
		
		Properties p = new Properties();
		p.load(Test03.class.getClassLoader().getResourceAsStream("classpath.properties"));
		String path = p.getProperty("path");
		
		@SuppressWarnings("unchecked")
		Class<Student> clazz = (Class<Student>) Class.forName(path);
		
		//获取该类以及父类公有的方法对象
//		Method[] methods = clazz.getMethods();
//		for (Method method : methods) {
//			System.out.println(method);
//		}
		
		//获取该类所有的方法对象
//		Method[] methods = clazz.getDeclaredMethods();
//		for (Method method : methods) {
//			System.out.println(method);
//		}
		
		//获取该类及其父类所有的方法对象
//		List<Method> list = ReflexUtil.getAllMethod(clazz);
//		for (Method method : list) {
//			System.out.println(method);
//		}
		
		//调用公有的方法 -- 无参数的方法
//		Student stu = ReflexUtil.newInstance(clazz,new Class[]{String.class,char.class,int.class,String.class,String.class},new Object[]{"刘备",'男',23,"2022","001"});
//		Method method = clazz.getMethod("getClassId");
//		Object invoke = method.invoke(stu);
//		System.out.println("返回值:" + invoke);
		
		//调用公有的方法 -- 有参数的方法
//		Student stu = ReflexUtil.newInstance(clazz,new Class[]{String.class,char.class,int.class,String.class,String.class},new Object[]{"刘备",'男',23,"2022","001"});
//		Method method = clazz.getMethod("setClassId",String.class);
//		Object invoke = method.invoke(stu,"2212");
//		System.out.println("返回值:" + invoke);
//		System.out.println(stu);
		
		//调用私有的方法
//		Student stu = ReflexUtil.newInstance(clazz,new Class[]{String.class,char.class,int.class,String.class,String.class},new Object[]{"刘备",'男',23,"2022","001"});
//		Method method = clazz.getDeclaredMethod("method01", String.class);
//		method.setAccessible(true);
//		Object invoke = method.invoke(stu, "abc");
//		System.out.println("返回值:" + invoke);
		
		//调用方法 -- 封装方法
//		Student stu = ReflexUtil.newInstance(clazz,new Class[]{String.class,char.class,int.class,String.class,String.class},new Object[]{"刘备",'男',23,"2022","001"});
//		Object invoke = ReflexUtil.invoke(stu, "method01", new Class[]{String.class}, new Object[]{"abc"});
//		System.out.println("返回值:" + invoke);
		
		
		//调用静态方法
		Object invoke = ReflexUtil.invoke(clazz, "method02", null,null);
		System.out.println("返回值:" + invoke);
	}
}

6.利用反射操作泛型

注意:类上的泛型是获取不到的

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;

public class Test06 {

	public static void main(String[] args) throws Exception {
		
		Class<?> clazz = Test06.class;
		Method method = clazz.getDeclaredMethod("method", ArrayList.class,HashMap.class);
		
		//获取参数上的泛型
		Type[] genericParameterTypes = method.getGenericParameterTypes();//获取参数类型
		for (Type type : genericParameterTypes) {
			ParameterizedType pt = (ParameterizedType) type;//把type强转为参数类型
			Type[] actualTypeArguments = pt.getActualTypeArguments();//获取参数类型上的泛型并返回泛型数组(为什么返回的是数组?因为一个参数上有可能有多个泛型)
			for (Type t : actualTypeArguments) {
				System.out.println(t);
			}
		}
		System.out.println("-------------");
		
		//获取返回值上的泛型
		Type genericReturnType = method.getGenericReturnType();
		ParameterizedType pt = (ParameterizedType)genericReturnType;
		Type[] actualTypeArguments = pt.getActualTypeArguments();//获取返回值类型上的泛型并返回泛型数组(为什么返回的是数组?因为一个参数上有可能有多个泛型)
		for (Type type : actualTypeArguments) {
			System.out.println(type);
		}
	}
	
	public HashMap<String, Integer> method(ArrayList<String> list,HashMap<String, Integer> map){
		return null;
	}
	
}

7.利用反射操作数组

Arrays -- 数组的工具类
Array --- 数组的反射类
import java.lang.reflect.Array;

public class Test07 {
	public static void main(String[] args) throws Exception {
		
		//创建数组
		int[] is = (int[]) Array.newInstance(int.class, 5);
		
		//获取数组的长度
		System.out.println("获取数组的长度:" + Array.getLength(is));//5
		
		//通过下标设置元素
		Array.set(is, 2, 888);
		
		//遍历数组
		for(int i = 0;i<Array.getLength(is);i++){
			//通过下标获取元素
			Object element = Array.get(is, i);
			System.out.println(element);
		}
		
	}
}

8.反射机制 之 扩展运用封装代码

public class Person {

	private String name;
	private char sex;
	private int age;
	
	public Person() {
	}

	public Person(String name, char sex, int age) {
		this.name = name;
		this.sex = sex;
		this.age = age;
	}

	public String getName() {
		return name;
	}

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

	public char getSex() {
		return sex;
	}

	public void setSex(char sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [names=" + name + ", sex=" + sex + ", age=" + age + "]";
	}
	
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

//反射工具类
public class ReflexUtil {

	//获取该类及其父类所有的属性对象
	public static List<Field> getAllField(Class<?> clazz){

		List<Field> list = new ArrayList<>();

		for (Class<?> c = clazz;c != null;c = c.getSuperclass()) {
			Field[] fields = c.getDeclaredFields();
			Collections.addAll(list, fields);
		}

		return list;
	}

	//获取该类及其父类指定的属性对象
	public static Field getField(Class<?> clazz,String fieldName){
		for (Class<?> c = clazz;c != null;c = c.getSuperclass()) {
			try {
				Field field = c.getDeclaredField(fieldName);
				return field;
			} catch (NoSuchFieldException e) {//如果该类中找不到属性就会出现该异常
			} 
		}
		return null;
	}

	//设置对象中的属性
	public static void setField(Object obj,String fieldName,Object value){

		Field field = getField(obj.getClass(), fieldName);
		field.setAccessible(true);
		try {
			field.set(obj, value);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}

	//获取该类及其父类所有的构造对象
	public static List<Constructor<?>> getAllConstructor(Class<?> clazz){

		List<Constructor<?>> list = new ArrayList<>();

		for (Class<?> c = clazz;c != null;c = c.getSuperclass()) {
			Constructor<?>[] constructors = c.getDeclaredConstructors();
			Collections.addAll(list, constructors);
		}

		return list;
	}

	//创建该类的对象
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] values){

		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T t = constructor.newInstance(values);
			return t;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return null;
	}

	//获取该类及其父类所有的方法对象
	public static List<Method> getAllMethod(Class<?> clazz){

		List<Method> list = new ArrayList<>();

		for (Class<?> c = clazz;c != null;c = c.getSuperclass()) {
			Method[] methods = c.getDeclaredMethods();
			Collections.addAll(list, methods);
		}

		return list;
	}

	//获取指定的方法对象
	public static Method getMethod(Class<?> clazz,String methodName,Class<?>... parameterTypes){
		for(Class<?> c = clazz;c != null;c = c.getSuperclass() ){
			try {
				Method method = c.getDeclaredMethod(methodName, parameterTypes);
				return method;
			} catch (NoSuchMethodException e) {
			} 
		}
		return null;
	}

	//调用成员方法
	public static Object invoke(Object obj,String methodName,Class<?>[] parameterTypes,Object[] values){
		Method method = getMethod(obj.getClass(), methodName, parameterTypes);
		method.setAccessible(true);
		try {
			Object invoke = method.invoke(obj, values);
			return invoke;
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	//调用静态方法
	public static Object invoke(Class<?> clazz,String methodName,Class<?>[] parameterTypes,Object[] values){
		Method method = getMethod(clazz, methodName, parameterTypes);
		method.setAccessible(true);
		try {
			Object invoke = method.invoke(null, values);//静态方法直接填null,因为不需要对象去调用
			return invoke;
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
		}
		return values;
	}
}
public class Student extends Person{
	
	private String classId;
	private String id;
	
	public Student() {
	}

	public Student(String name, char sex, int age, String classId, String id) {
		super(name, sex, age);
		this.classId = classId;
		this.id = id;
	}

	public String getClassId() {
		return classId;
	}

	public void setClassId(String classId) {
		this.classId = classId;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}



//	private String method01(String str){
//	System.out.println("私有的方法 :" + str);
//	return "用良心做教育";
//}
	
	@Override
	public String toString() {
		return "Student [classId=" + classId + ", id=" + id + ", getName()=" + getName() + ", getSex()=" + getSex()
				+ ", getAge()=" + getAge() + "]";
	}

	public static void method02(){
		System.out.println("静态的方法");
	}
}

9.反射机制 之 扩展属性的运用

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Properties;

public class Test01 {

	public static void main(String[] args) throws Exception {
		
		Properties p = new Properties();
		p.load(Test01.class.getClassLoader().getResourceAsStream("classpath.properties"));
		String path = p.getProperty("path");
		
		Class<?> clazz = Class.forName(path);
		
		//获取学生类中的name属性
		Field field = ReflexUtil.getField(clazz, "name");
		
		//获取属性参数值
		int modifiers = field.getModifiers();
		
		System.out.println("判断属性是否是私有化的:" + Modifier.isPrivate(modifiers));
		System.out.println("判断属性是否是Protected的:" + Modifier.isProtected(modifiers));
		System.out.println("判断属性是否是公有的:" + Modifier.isPublic(modifiers));
		System.out.println("判断属性是否是静态的:" + Modifier.isStatic(modifiers));
		System.out.println("判断属性是否是常量的:" + Modifier.isFinal(modifiers));
	}
}

10.反射机制 之 扩展方法的运用

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Properties;

public class Test02 {

	@SuppressWarnings("all")
	public static void main(String[] args) throws Exception {
		
		Properties p = new Properties();
		p.load(Test02.class.getClassLoader().getResourceAsStream("classpath.properties"));
		String path = p.getProperty("path");
		
		Class<?> clazz = Class.forName(path);
		
		//获取学生类中的method02
		Method method = ReflexUtil.getMethod(clazz, "method02",null);
		
		//获取方法参数值
		int modifiers = method.getModifiers();
		
		System.out.println("判断方法是否是私有化的:" + Modifier.isPrivate(modifiers));
		System.out.println("判断方法是否是Protected的:" + Modifier.isProtected(modifiers));
		System.out.println("判断方法是否是公有的:" + Modifier.isPublic(modifiers));
		System.out.println("判断方法是否是静态的:" + Modifier.isStatic(modifiers));
		System.out.println("判断方法是否不可重写的:" + Modifier.isFinal(modifiers));
		System.out.println("判断方法是否同步的:" + Modifier.isSynchronized(modifiers));
		System.out.println("判断方法是否抽象的:" + Modifier.isAbstract(modifiers));
	}
}

11.反射案例之万能数组扩容/复制

import java.lang.reflect.Array;
import java.util.Arrays;

public class Test01 {

	public static void main(String[] args) {
		
		int[] is = {1,2,3,4,5};
		int[] copy1 = copy(is,10);
		System.out.println(Arrays.toString(copy1));
		
		System.out.println("---------");
		
		String[] names = {"后裔","狄仁杰","李元芳","孙尚香"};
		String[] copy2 = copy(names,10);
		System.out.println(Arrays.toString(copy2));
	}
	
	public static <T> T copy(T t,int newLength){
		//获取数组的class对象
		Class<? extends Object> clazz = t.getClass();
		//获取数组元素类型的class对象
		Class<?> elementClazz = clazz.getComponentType();
		//创建数组
		@SuppressWarnings("unchecked")
		T arr = (T) Array.newInstance(elementClazz, newLength);
		//遍历原数组
		for (int i = 0; i < Array.getLength(t); i++) {
			//获取指定下标上的元素
			Object element = Array.get(t, i);
			//将元素设置给新数组
			Array.set(arr, i, element);
		}
		return arr;
	}
}

12.反射案例 之 逻辑与业务分离的思想

  • 业务场景:获取数据
  • 分析:
  • 获取本地数据 – 代码
  • 获取网络数据 – 代码
  • 获取其他数据 – 代码
import java.util.List;
import java.util.Scanner;

public class Test01 {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		printMenu();
		int num = scan.nextInt();
		
		DataSource dataSource =	getDataSourceObj(num);
		dataSource.getDataSource();
		
		scan.close();
	}

		public static DataSource getDataSourceObj(int num){
			List<String> classlist = DataContainer.classList;
			String classPath = classlist.get(num-1);
			try {
				Class<?> clazz = Class.forName(classPath);
				DataSource dataSource = (DataSource) clazz.newInstance();
				return dataSource;
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		
		return null;
		
	}

	private static void printMenu() {
		List<String> menulist = DataContainer.menuList;
		System.out.println("请选择获取数据的方式:");
		for (String str : menulist) {
			System.out.println(str);
		}
	}
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class DataContainer {

	public static final List<String> menuList;
	public static final List<String> classList;
	
	static{
		//初始化菜单集合
		menuList = new ArrayList<>();
		Properties menuProperties = new Properties();
		
		try {
			menuProperties.load(DataContainer.class.getClassLoader().getResourceAsStream("menuConfig.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		String menu = menuProperties.getProperty("menu");
		String[] menuSplit = menu.split(",");
		for (String str : menuSplit) {
			menuList.add(str);
		}
		
		//初始化类路径集合
		classList = new ArrayList<>();
		Properties classProperties = new Properties();
		
		try {
			classProperties.load(DataContainer.class.getClassLoader().getResourceAsStream("classConfig.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String path = classProperties.getProperty("path");
		String[] pathSplit = path.split(",");
		for (String str : pathSplit) {
			classList.add(str);
		}
	}
}
public abstract class DataSource {
	public abstract void getDataSource();
}
public class LocalDataSource extends DataSource{

	@Override
	public void getDataSource() {
		System.out.println("执行获取本地数据的代码...");
		
	}

}
public class NetworkDataSource extends DataSource{

	@Override
	public void getDataSource() {
		System.out.println("执行获取网络数据的代码...");
		
	}

}
public class OtherDataSource extends DataSource{

	@Override
	public void getDataSource() {
		System.out.println("执行获取其他数据的代码...");
		
	}

}

13.反射案例 之 获取注解信息

import java.lang.reflect.Field;

public class Test01 {

	public static void main(String[] args) {

		Student stu = new Student("刘备", '男', 23);

		Class<? extends Student> clazz = stu.getClass();

		//获取类上注解的信息
		TableInfo tableInfoAnnotation = clazz.getAnnotation(TableInfo.class);
		String tableName = tableInfoAnnotation.value();
		System.out.println(tableName);

		//获取属性上注解的信息
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			FieldInfo fieldInfoAnnotation = field.getAnnotation(FieldInfo.class);
			String name = fieldInfoAnnotation.name();
			String type = fieldInfoAnnotation.type();
			int length = fieldInfoAnnotation.length();

			Object value = null;
			try {
				field.setAccessible(true);
				value = field.get(stu);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}

			System.out.println(name + " -- " + type + " -- " + length + " -- " + value);
		}


		//insert into s_student(s_name,s_sex,s_age) values("刘备","男",23)
	}
}
@TableInfo("s_student")
public class Student {

	@FieldInfo(name="s_name",type="varchar",length=32)
	private String name;
	
	@FieldInfo(name="s_sex",type="varchar",length=32)
	private char sex;
	
	@FieldInfo(name="s_age",type="int",length=3)
	private int age;
	
	public Student() {
	}

	public Student(String name, char sex, int age) {
		this.name = name;
		this.sex = sex;
		this.age = age;
	}

	public String getName() {
		return name;
	}

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

	public char getSex() {
		return sex;
	}

	public void setSex(char sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}
	
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableInfo {

	String value();
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldInfo {

	String name();
	String type();
	int length();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨霖先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值