• 学习JavaEE的日子 Day39 注解,反射


    Day39

    注解

    1.什么是注解

    理解:给程序员和程序解释代码信息

    2.注解与注释的区别

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

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

    3.注解的所用

    可以作用于包、类、方法、属性上,给他们添加额外的信息,可以被其他程序(编译器)读取

    4.注解的格式

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

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

    5.注解的应用

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

    6.内置注解

    理解:Java给我们提供个注解

    *@Overrlde*:表示该方法是重写父类的方法

    *@Deprecated*:表示该方法已过时

    *@SuppressWarnings*:镇压警告,定义在java.lang.SuppressWarnings中用来抑制编译时的警告信息,与前两个注释有所不同.你需要添加参数才能正确使用。(镇压报小黄线的地方)

    @SuppressWarnings(“all”)抑制所有类型的警告信息

    @SuppressWarnings(“unchecked”)抑制单类型的警告信息

    @SuppressWarnings(value={“unchecked”,“deprecation”})抑制多类型的警告信息

    public class Test01 {
    	
    	//@Override表示该方法是重写父类的方法
    	@Override
    	public String toString() {
    		return super.toString();
    	}
    	
    	//@Deprecated表示该方法已过时
    	@Deprecated
    	public void method01(){
    	}
    	
    	//@SuppressWarnings表示镇压警告的注解
    	@SuppressWarnings("all")
    	public void method02(){
    		
    		ArrayList list = new ArrayList();
    		list.add(100);
    		list.add(123.123);
    		list.add("用良心做教育");
    	}
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    7.元注解

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

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

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

    • ElementType.TYPE 类上
    • ElementType.FIELD 属性上
    • ElementType.METHOD 方法上
    • ElementType.PARAMETER 参数上
    • ElementType.LOCAL_VARIABLE 局部变量上
    • ElementType.TYPE_PARAMETER 泛型上

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

    SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在

    CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值

    RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段

    (SOURCE < CLASS < *RUNTIME*)

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

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

    8.自定义注解

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

    分析:

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

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

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

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

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

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

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

    @MyAnnotaction
    public class Test01<@MyAnnotaction T> {
    	public static void main(String[] args) {
    		
    	}
    	
    	@MyAnnotaction
    	String attr;
    
    	@MyAnnotaction
    	public static void method(@MyAnnotaction String str){
    		
    		@MyAnnotaction
    		int i = 100;
    		System.out.println(i);
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    自定义注解类

    //@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE,ElementType.TYPE_PARAMETER})
    //@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER,ElementType.LOCAL_VARIABLE,ElementType.TYPE_PARAMETER})
    @Target({TYPE,FIELD,METHOD,PARAMETER,LOCAL_VARIABLE,TYPE_PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotaction {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意:

    当注解中只有"一个属性",并且属性名是"value",使用注解时,可以省略value属性名:public String value(); @Anno2(“123”)

    反射

    1.Java的反射机制

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    前言:

    使用到一个类,JVM会将该类的class文件加载到方法区(类加载机制),同时会在堆内存中创建该类的class对象,class对象的作为class文件的访问入口

    理解:

    反射实际上就是获取class对象,通过class对象访问class文件中的内容

    访问内容:属性;构造方法;普通方法(成员方法、静态方法、抽象方法…);方法上的参数;方法上的返回值;数组

    注意:对于反射来说,一个类就是透明的,没有穿衣服的

    2.关键点-获取Class文件对象

    注意:

    该类的class文件只在一次到方法区中,该类的class对象在程序中是唯一的。所以不管使用那种方式获取class对象都是同一个

    public class Test01 {
    	public static void main(String[] args) throws ClassNotFoundException {
    		
    		//获取class对象方式1
    		Class<? extends Student> clazz1 = Student.class;
    		
    		//获取class对象方式2
    		Student stu = new Student();
    		Class<? extends Student> clazz2 = stu.getClass();
    		
    		//获取class方式3(一般使用这个)
    		Class<?> clazz3 = Class.forName("com.qf.reflex01.Student");
    		
    		System.out.println(clazz1 == clazz2);//true
    		System.out.println(clazz1 == clazz3);//true
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    经验:配置文件 + Class.forName() --常用

    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<?> clazz = Class.forName(path);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    classPath.properties

    path=com.qf.reflex01.Student
    
    • 1

    3.利用反射操作属性

    Field[] getFields():返回所有成员变量对象的数组(只能拿public的)

    Field[] getDeclaredFields():返回所有成员变量对象的数组,存在就能拿到

    Field getField(String name):返回单个成员变量对象(只能拿public的)

    Field getDeclaredField(String name):返回单个成员变量对象,存在就能拿到

    注意:如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用

    获取成员变量并获取值和修改值

    void set(Object obj, Object value):赋值

    Object get(Object obj):获取值

    public class Test03 {
    	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
    		
    //		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);
    //		}
    		
    		//获取本类及其父类所有的属性对象
    //		for(Class c = clazz;c!=null;c=c.getSuperclass()){
    //			Field[] fields = c.getDeclaredFields();
    //			for (Field field : fields) {
    //				System.out.println(field);
    //			}
    //		}
    		
    		
    //		try {
    //			//获取本类指定的属性对象
    //			Field field = clazz.getDeclaredField("str");
    //			System.out.println(field);
    //			
    //			//获取属性参数值
    //			int modifiers = field.getModifiers();
    //			System.out.println("是否使用public修饰:" + Modifier.isPublic(modifiers));
    //			System.out.println("是否使用stati修饰:" + Modifier.isStatic(modifiers));
    //			System.out.println("是否使用final修饰:" + Modifier.isFinal(modifiers));
    //			System.out.println("是否使用private修饰:" + Modifier.isPrivate(modifiers));
    //			System.out.println("是否使用protected修饰:" + Modifier.isProtected(modifiers));
    //			System.out.println("是否使用transient修饰:" + Modifier.isTransient(modifiers));
    //			
    //		} catch (NoSuchFieldException e) {//属性名没有配到对应的属性就报该异常
    //			e.printStackTrace();
    //		} catch (SecurityException e) {
    //			e.printStackTrace();
    //		}
    		
    		//通过反射设置对象里的属性
    //		Student stu = new Student("巴得伟", '男', 23, "2401", "001");
    //		Field field = clazz.getDeclaredField("id");
    //		field.setAccessible(true);//设置修改权限
    //		field.set(stu, "666");//设置stu对象里的id属性为"666"的值
    //		System.out.println(stu);
    		
    		//通过反射工具类设置对象里的属性
    		Student stu = new Student();
    		ReflexUtil.setField(stu, "name", "巴得伟");
    		ReflexUtil.setField(stu, "sex", '男');
    		ReflexUtil.setField(stu, "age", 23);
    		ReflexUtil.setField(stu, "classId", "2401");
    		ReflexUtil.setField(stu, "id", "001");
    		
    		System.out.println(stu);
    	}
    }
    
    
    • 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
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    Person类

    package com.qf.reflex01;
    
    public class Person {
    
    	private String name;
    	private char sex;
    	private int age;
    	
    	//无参构造,有参构造,set,get省略
        
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
    	}
    	
    	protected static final synchronized void method(){
    		System.out.println("静态方法");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Person类的子类

    @MyAnnotaction(str = "aaa")
    public class Student extends Person{
    	
    	private String classId;
    	private String id;
    	
    	@MyAnnotaction(str = "bbb")
    	public HashMap<String, Integer> map;
    	
    	public static final String str = "用良心做教育";
    
         //无参构造,有参构造,set,get省略 
    
    	@Override
    	public String toString() {
    		return "Student [classId=" + classId + ", id=" + id + ", toString()=" + super.toString() + "]";
    	}
    	
    	public void method01(){
    		System.out.println("无参数无返回值的方法 -- method01");
    	}
    	
    	public void method02(String str, int i){
    		System.out.println("带参数的方法 -- method02:" + str + " -- " + i);
    	}
    	
    	public String method03(){
    		return "无参数带返回值的方法 -- method03";
    	}
    	
    	private String method04(String str, int i){
    		return "带参数带返回值的方法 -- method04:" + str + " -- " + i;
    	}
    	
    	@MyAnnotaction(str = "ccc")
    	public HashMap<Character, Boolean> method05(@MyAnnotaction(str = "ddd") ArrayList<Object> list,HashMap<Number, Double> map){
    		return null;
    	}
    }
    
    
    • 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

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

    Constructor[] getConstructors():获得所有的构造(只能public修饰)

    Constructor[] getDeclaredConstructors():获得所有的构造(包含private修饰)

    Constructor getConstructor(Class… parameterTypes):获取指定构造(只能public修饰)

    Constructor getDeclaredConstructor(Class… parameterTypes):获取指定构造(包含private修饰)

    newInstance():获取构造方法并创建对象的方法

    public class Test04 {
    	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    		
    //		Properties p = new Properties();
    //		p.load(Test04.class.getClassLoader().getResourceAsStream("classPath.properties"));
    //		String path = p.getProperty("path");
    		
    //		Class clazz = 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);
    //		}
    		
    		//获取无参构造对象
    //		Constructor constructor = clazz.getDeclaredConstructor();
    //		//利用无参构造对象创建该类的对象
    //		constructor.setAccessible(true);//设置修改权限
    //		Student stu = (Student) constructor.newInstance();
    //		System.out.println(stu);
    		
    		//利用无参构造对象创建该类的对象 -- 简化版
    //		Student stu = (Student) clazz.newInstance();
    //		System.out.println(stu);
    		
    		//获取有参构造对象
    //		Constructor constructor = clazz.getDeclaredConstructor(String.class,char.class,int.class,String.class,String.class);
    //		//利用有参构造对象创建该类的对象
    //		constructor.setAccessible(true);//设置修改权限
    //		Student stu = (Student) constructor.newInstance("巴得伟",'男',23,"2401","001");
    //		System.out.println(stu);
    		
    		//利用反射工具类去创建对象 -- 底层调用无参构造
    //		Student stu = ReflexUtil.newInstance(Student.class, null, null);
    //		System.out.println(stu);
    		
    		//利用反射工具类去创建对象 -- 底层调用有参构造
    		Class<?>[] parameterTypes = {String.class,char.class,int.class,String.class,String.class};
    		Object[] paremeters = {"巴得伟",'男',23,"2401","001"};
    		Student stu = ReflexUtil.newInstance(Student.class, parameterTypes, paremeters);
    		System.out.println(stu);
    	}
    }
    
    
    
    • 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
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    5.利用反射操作方法

    Method[] getMethods():返回所有成员方法对象的数组(只能拿public的)

    Method[] getDeclaredMethods():返回所有成员方法对象的数组,存在就能拿到

    Method getMethod(String name, Class… parameterTypes):返回单个成员方法对象(只能拿public的)

    Method getDeclaredMethod(String name, Class… parameterTypes):返回单个成员方法对象,存在就能拿到

    如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用

    public class Test01 {
    	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException {
    		
    //		Properties p = new Properties();
    //		p.load(Test01.class.getClassLoader().getResourceAsStream("classPath.properties"));
    //		String path = p.getProperty("path");
    
    //		Class clazz = 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);
    //		}
    		
    		//获取本类及其父类所有的方法对象
    //		for (Class c = clazz; c != null; c = c.getSuperclass()) {
    //			Method[] methods = c.getDeclaredMethods();
    //			for (Method method : methods) {
    //				System.out.println(method);
    //			}
    //		}
    		
    		//获取本类公有的指定名字的方法对象
    //		Method method = clazz.getMethod("setClassId", String.class);
    //		System.out.println(method);
    		
    		//获取本类所有的指定名字的方法对象
    //		Method method = clazz.getDeclaredMethod("method");
    //		System.out.println(method);
    		
    		//利用反射工具类获取子类及其父类指定名字的方法对象
    //		Method method = ReflexUtil.getMethod(clazz, "method");
    //		System.out.println(method);
    		//获取方法参数值
    //		int modifiers = method.getModifiers();
    //		System.out.println("是否使用public修饰:" + Modifier.isPublic(modifiers));
    //		System.out.println("是否使用private修饰:" + Modifier.isPrivate(modifiers));
    //		System.out.println("是否使用protected修饰:" + Modifier.isProtected(modifiers));
    //		System.out.println("是否使用static修饰:" + Modifier.isStatic(modifiers));
    //		System.out.println("是否使用final修饰:" + Modifier.isFinal(modifiers));
    //		System.out.println("是否使用abstract修饰:" + Modifier.isAbstract(modifiers));
    //		System.out.println("是否使用synchronized修饰:" + Modifier.isSynchronized(modifiers));
    		
    	}
    }
    
    
    • 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
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    6.利用反射操作方法

    public class Test02 {
    	public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    		
    		Properties p = new Properties();
    		p.load(Test02.class.getClassLoader().getResourceAsStream("classPath.properties"));
    		String path = p.getProperty("path");
    
    		Class<?> clazz = Class.forName(path);
    		
    //		//利用反射调用静态方法
    //		Method method = ReflexUtil.getMethod(clazz, "method");
    //		method.invoke(null);//静态方法不需要对象调用,就传入null
    //		
    //		Student stu = new Student();
    //		
    //		//利用反射调用成员方法 -- 无参数无返回值的方法
    //		Method method01 = ReflexUtil.getMethod(clazz, "method01");
    //		method01.invoke(stu);
    //	
    //		//利用反射调用成员方法 -- 带参数的方法
    //		Method method02 = ReflexUtil.getMethod(clazz, "method02", String.class,int.class);
    //		method02.invoke(stu, "用良心做教育",100);
    //		
    //		//利用反射调用成员方法 -- 无参数带返回值的方法
    //		Method method03 = ReflexUtil.getMethod(clazz, "method03");
    //		String returnVal1 = (String) method03.invoke(stu);
    //		System.out.println(returnVal1);
    //		
    //		//利用反射调用成员方法 -- 带参数带返回值的方法
    //		Method method04 = ReflexUtil.getMethod(clazz, "method04", String.class,int.class);
    //		method04.setAccessible(true);//设置修改权限
    //		String returnVal2 = (String) method04.invoke(stu, "用良心做教育",200);
    //		System.out.println(returnVal2);
    		
    		//利用反射工具类 -- 调用静态方法
    		ReflexUtil.invoke(clazz, "method", null, null);
    		
    		Student stu = new Student();
    		
    		//利用反射工具类 -- 反射调用成员方法 -- 无参数无返回值的方法
    		ReflexUtil.invoke(stu, "method01", null, null);
    		
    		//利用反射工具类 -- 反射调用成员方法 -- 带参数的方法
    		ReflexUtil.invoke(stu, "method02", new Class[]{String.class,int.class}, new Object[]{"用良心做教育",100});
    		
    		//利用反射工具类 -- 反射调用成员方法 -- 无参数带返回值的方法
    		Object returnVal1 = ReflexUtil.invoke(stu, "method03", null, null);
    		System.out.println(returnVal1);
    		
    		//利用反射工具类 -- 反射调用成员方法 -- 带参数带返回值的方法
    		Object returnVal2 = ReflexUtil.invoke(stu, "method04", new Class[]{String.class,int.class}, new Object[]{"用良心做教育",100});
    		System.out.println(returnVal2);
    	}
    }
    
    
    • 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
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    7.利用反射操作 方法里的参数和返回值

    public class Test03 {
    	public static void main(String[] args) throws IOException, ClassNotFoundException {
    		
    		Properties p = new Properties();
    		p.load(Test03.class.getClassLoader().getResourceAsStream("classPath.properties"));
    		String path = p.getProperty("path");
    
    		Class<?> clazz = Class.forName(path);
    		
    		//利用反射工具类获取方法对象
    		Method method = ReflexUtil.getMethod(clazz, "method04", String.class,int.class);
    		
    		//获取方法的参数个数
    		int parameterCount = method.getParameterCount();
    		System.out.println("获取方法的参数个数:" + parameterCount);
    		
    		System.out.println("-----------------------------");
    		
    		//获取方法参数的class对象数组
    		Class<?>[] parameterTypes = method.getParameterTypes();
    		for (Class<?> c : parameterTypes) {
    			System.out.println(c);
    		}
    		
    		System.out.println("-----------------------------");
    		
    		//获取方法参数的Type对象数组
    		//一个参数类型就是一个Type对象
    		Type[] genericParameterTypes = method.getGenericParameterTypes();
    		for (Type type : genericParameterTypes) {
    			System.out.println(type);
    		}
    		
    		System.out.println("-----------------------------");
    		
    		//获取方法参数对象数组
    		//一个参数就是一个参数对象
    		Parameter[] parameters = method.getParameters();
    		for (Parameter parameter : parameters) {
    			
    			System.out.println("获取方法的参数类型:" + parameter.getType());
    			
    			/**
    			 * 注意:
    			 * 		参数名不会随着编译而编译到class文件,
    			 * 		class文件描述该方法的参数名使用的是:arg0,arg1,arg2,.....
    			 */
    			System.out.println("获取方法的参数名:" + parameter.getName());
    		}
    		
    		System.out.println("-----------------------------");
    		
    		//获取返回值的class对象
    		Class<?> returnType = method.getReturnType();
    		System.out.println("获取返回值的class对象:" + returnType);
    		
    		//获取返回值的Type对象
    		Type genericReturnType = method.getGenericReturnType();
    		System.out.println("获取返回值的Type对象:" + genericReturnType);
    	}
    }
    
    
    • 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
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    8.利用反射操作泛型

    注意:

    集合中的泛型只在java文件中存在,当编译成class文件之后,就没有泛型了。

    类上的泛型是获取不到的,因为不固定!!!

    class A{}

    public class Test04 {
    	public static void main(String[] args) throws IOException, ClassNotFoundException {
    		
    		Properties p = new Properties();
    		p.load(Test04.class.getClassLoader().getResourceAsStream("classPath.properties"));
    		String path = p.getProperty("path");
    
    		Class<?> clazz = Class.forName(path);
    		
    		
    		//获取属性上的泛型类型
    		Field field = ReflexUtil.getField(clazz, "map");
    		Type fieldType = field.getGenericType();
    		ParameterizedType fieldTypepPT = (ParameterizedType) fieldType;
    		Type[] actualTypeArguments = fieldTypepPT.getActualTypeArguments();//获取泛型类型
    		for (Type type : actualTypeArguments) {
    			System.out.println(type);
    		}
    		
    		System.out.println("---------------------------------------");
    		
    		Method method = ReflexUtil.getMethod(clazz, "method05", ArrayList.class,HashMap.class);
    		
    		//获取方法上参数的泛型类型
    		Parameter[] parameters = method.getParameters();
    		for (Parameter parameter : parameters) {
    			Type parameterizedType = parameter.getParameterizedType();
    			ParameterizedType parameterTypepPT = (ParameterizedType) parameterizedType;
    			Type[] actualTypeArguments2 = parameterTypepPT.getActualTypeArguments();
    			for (Type type : actualTypeArguments2) {
    				System.out.println(type);
    			}
    		}
    		
    		System.out.println("---------------------------------------");
    		
    		//获取方法上返回值的泛型类型
    		Type genericReturnType = method.getGenericReturnType();
    		ParameterizedType returnPT = (ParameterizedType) genericReturnType;
    		Type[] actualTypeArguments2 = returnPT.getActualTypeArguments();
    		for (Type type : actualTypeArguments2) {
    			System.out.println(type);
    		}
    	}
    }
    
    
    • 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

    9.利用反射操作注解

    public class Test05 {
    	public static void main(String[] args) throws IOException, ClassNotFoundException {
    		
    		Properties p = new Properties();
    		p.load(Test05.class.getClassLoader().getResourceAsStream("classPath.properties"));
    		String path = p.getProperty("path");
    
    		Class<?> clazz = Class.forName(path);
    		
    		//获取类上的注解信息
    		MyAnnotaction classAnnotation = clazz.getAnnotation(MyAnnotaction.class);
    		System.out.println(classAnnotation.str());
    	
    		System.out.println("------------------------------------------------");
    		
    		//获取属性上的注解信息
    		Field field = ReflexUtil.getField(clazz, "map");
    		MyAnnotaction fieldAnnotation = field.getAnnotation(MyAnnotaction.class);
    		System.out.println(fieldAnnotation.str());
    		
    		System.out.println("------------------------------------------------");
    		
    		//获取方法上的注解信息
    		Method method = ReflexUtil.getMethod(clazz, "method05", ArrayList.class,HashMap.class);
    		MyAnnotaction methodAnnotation = method.getAnnotation(MyAnnotaction.class);
    		System.out.println(methodAnnotation.str());
    		
    		System.out.println("------------------------------------------------");
    		
    		//获取参数上的注解信息
    		Parameter[] parameters = method.getParameters();
    		for (Parameter parameter : parameters) {
    			MyAnnotaction parameterAnnotation = parameter.getAnnotation(MyAnnotaction.class);
    			if(parameterAnnotation != null){//说明该参数上有MyAnnotaction的注解
    				System.out.println(parameterAnnotation.str());
    			}
    		}	
    		
    	}
    }
    
    
    • 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

    MyAnnotaction类

    @Target({TYPE,FIELD,METHOD,PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotaction {
    	
    	String str();
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    10.利用反射操作数组

    注意:Array – 该类是Java给我们提供专门利用反射去操作数组的类

    public class Test06 {
    	public static void main(String[] args) {
    		
    		//创建数组
    		int[] arr = (int[]) Array.newInstance(int.class, 10);
    		
    		//获取数组长度
    		int length = Array.getLength(arr);
    		System.out.println("获取数组长度:" + length);
    		
    		//循环设置每个下标上的元素
    		for (int i = 0; i < Array.getLength(arr); i++) {
    			//设置当前下标上的元素
    			Array.set(arr, i, i+1);
    		}
    		
    		//循环获取每个下标上的元素
    		for (int i = 0; i < Array.getLength(arr); i++) {
    			//获取当前下标上的元素
    			Object element = Array.get(arr, i);
    			System.out.println(element);
    		}
    	}
    }
    
    
    • 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

    10.反射工具类

    package com.qf.utils;
    
    public class ReflexUtil {
    
    	/**
    	 * 获取当前类及其父类的属性对象
    	 * @param clazz class对象
    	 * @param name 属性名
    	 * @return 属性对象
    	 */
    	public static Field getField(Class<?> clazz,String name){
    		
    		for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
    			try {
    				Field field = c.getDeclaredField(name);
    				return field;
    			} catch (NoSuchFieldException e) {
    			} catch (SecurityException e) {
    			}
    		}
    		return null;
    	}
    	
    	/**
    	 * 设置对象中的属性
    	 * @param obj 对象
    	 * @param name 属性名
    	 * @param value 属性值
    	 */
    	public static void setField(Object obj,String name,Object value){
    		
    		Field field = getField(obj.getClass(), name);
    		if(field != null){
    			field.setAccessible(true);
    			try {
    				field.set(obj, value);
    			} catch (IllegalArgumentException e) {
    				e.printStackTrace();
    			} catch (IllegalAccessException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	/**
    	 * 创建对象
    	 * @param clazz class对象
    	 * @param paremeterType 构造方法中的参数类型数组
    	 * @param paremeters 构造方法中的参数数据
    	 * @return 对象
    	 */
    	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){
    		
    		try {
    			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
    			constructor.setAccessible(true);
    			T obj = constructor.newInstance(paremeters);
    			return obj;
    		} 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;
    	}
    
    	/**
    	 * 获取方法对象
    	 * @param clazz class对象
    	 * @param name 方法名
    	 * @param parameterTypes 参数列表数组
    	 * @return 方法对象
    	 */
    	public static Method getMethod(Class<?> clazz,String name,Class<?>... parameterTypes){
    		
    		for(Class<?> c = clazz; c != null; c = c.getSuperclass()) {
    			try {
    				Method method = c.getDeclaredMethod(name, parameterTypes);
    				return method;
    			} catch (NoSuchMethodException e) {
    			} catch (SecurityException e) {
    			}
    		}
    		
    		return null;
    	}
    
    	/**
    	 * 调用成员方法
    	 * @param obj 对象
    	 * @param name 方法名
    	 * @param parameterTypes 参数列表数组
    	 * @param paremeters 参数数据数组
    	 * @return 方法返回值
    	 */
    	public static Object invoke(Object obj,String name,Class<?>[] parameterTypes,Object[] paremeters){
    		
    		Class<? extends Object> clazz = obj.getClass();
    		
    		Method method = getMethod(clazz, name, parameterTypes);
    		method.setAccessible(true);
    		
    		try {
    			Object invoke = method.invoke(obj, paremeters);
    			return invoke;
    		} catch (IllegalAccessException e) {
    		} catch (IllegalArgumentException e) {
    		} catch (InvocationTargetException e) {
    		}
    		return null;
    	}
    	
    	/**
    	 * 调用静态方法
    	 * @param clazz class对象
    	 * @param name 方法名
    	 * @param parameterTypes 参数列表数组
    	 * @param paremeters 参数数据数组
    	 * @return 方法返回值
    	 */
    	public static Object invoke(Class<?> clazz,String name,Class<?>[] parameterTypes,Object[] paremeters){
    		
    		Method method = getMethod(clazz, name, parameterTypes);
    		method.setAccessible(true);
    		
    		try {
    			Object invoke = method.invoke(null, paremeters);
    			return invoke;
    		} catch (IllegalAccessException e) {
    		} catch (IllegalArgumentException e) {
    		} catch (InvocationTargetException e) {
    		}
    		return null;
    	}
    }
    
    
    • 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
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144

    简答题

    1.获取Class实例的方式
    类名.class
    对象.getClass
    类的全限定类名

    2.如何通过反射创建类对象
    Class aClass = Class.forName();
    Constructor c = aClass.getConstructor(String.class);
    Object o = c.newInstance(“hello”);

    3.如何通过反射调用方法、设置字段
    Method method = aClass.getMethod(“print”,String.class);
    Object h = method.invoke(o,“你好”);
    Field field = aClass.getField(“username”);
    field.set(o,“Tom”);
    Object f = field.get(o);

    4.反射机制的优缺点:
    优点:
    1)能够运行时动态获取类的实例,提高灵活性;
    2)与动态编译结合
    缺点:
    1)使用反射性能较低,需要解析字节码,将内存中的对象进行解析。
    2)相对不安全,破坏了封装性(因为通过反射可以获得私有方法和属性)

    5.哪里会用到反射机制?
    jdbc就是典型的反射

    Class.forName('com.mysql.jdbc.Driver.class');//加载MySQL的驱动类
    
    • 1

    这就是反射。如hibernate,struts等框架使用反射实现的。

    总结

    反射

    获取class对象

    操作属性

    操作构造方法

    操作方法

    操作方法里的参数

    操作方法里的返回值

    操作泛型

    操作注解

    操作数组

    重点:封装反射的工具类

  • 相关阅读:
    Linux下,查看 可执行文件 依赖的 动态库的几个方法
    力扣:169. 多数元素(Python3)
    kube-proxy的三种工作模式
    如何下载安装RabbitMQ
    ClickHouse配置Hdfs存储数据
    编译和连接
    深入理解Docker之:存储卷相关概念详解和分析
    在Java中线程和进程的区别
    基于Python文本内容/情感的对微博文本自动二元分类
    python pip 安装 Crypto 不可用解决方案
  • 原文地址:https://blog.csdn.net/weixin_69595694/article/details/137874639