java-反射、注解

一、类加载
时机:
创建对象的实例
调用该类的静态方法
使用反射方式强制创建某类或者接口的java.lang.Class对象
初始化某个子类
直接使用java.exe命令运行某个主类
二、类加载器
1.概述: 负责将Class文件加载到内存中,并为之生成对应的Class对象
把Hello.class字节码文件中Hello类加载到内存的过程

java Hello就会触发java类加载
2.分类:
①.启动类加载器 /jre/lib/rt.jar JAVA核心类加载
②.扩展类加载器 jre/lib/ext/.jar JRE中jar包,JDK中JRE的lib目录下的ext目录
③.本地类加载 classpath:. java命令的class文件,classpath环境变量所指的jar包,类路径
为了避免类的重复加载
3.双亲委托机制:
①.执行java Hello命令时候开始类加载(得到加载类的指令)
②.本地类加载器接到加载Hello类的指令,但是不做处理,反馈给上级扩展类加载器
③.扩展类加载器得到加载Hello类的指令,但是也不做处理,反馈给上级启动类加载器
④.启动类加载器得到加载Hello类的指令,直接处理,进行类加载。加载rt.jar中的类,但是
没有加载到Hello的类,接着启动类加载器又把加载 Hello类的指令向下交给扩展类加载器进行完成
⑤.扩展类加载器得到上级分配的任务:加载HelloWorld类,立刻加载jre/lib/ext/*.jar,但是
也没有加载到Hello的类,接着扩展类加载器又把加载Hello类的指向下交给本地类加载器进行完成。
⑥.本地类加载器得到上级分配的任务:加载Hello类,立刻执行加载ClassPath下的类,如果
加载到了Hello类,调用main方法执行,如果没有加载到Hello类就报异常,ClassNotFindException
类找不到。

三、反射
1.概述: 利用类加载时在堆中创建的java.lang.Class对象去获得该类加载以后在方法区中
创建的类信息,方法信息,变量信息…(一个对象获取自身的Class对象的过程)
2.作用: 可以帮你获取指定类的细节对象
3.获取字节码对象的方式:
①.Class.forName(“全限定名=包名+类名”)
②.类名.Class
③.对象.getClass()
利用该类的Class对象可以创建对象,访问属性,访问方法,访问构造器
4.反射对象的创建
自己不能创建,是由JVM在执行完类加载后会给加载器类创建它的镜像,因为类只
加载一次,所以任意类的Class对象在内存中只有一个
反射创建对象的两种方式:
①.直接用class.newInstance();//调用无参构造器创建对象
②.利用class获得有参构造器,然后调用newInstance(参数…);
5.细节对象
①.构造器
newInstance 调用无参构造器,必须存在public构造器
clazz.getConstructors() 获取所有public构造器
clazz.getDeclaredConstructors()获取所有构造器包括私有
clazz.getConstructor(Class…paraTypes) 获取指定公有构造器
clazz.getDeclaredConstructor(Class…paraTypes) 可获取指定私有构造器
②.通过成员变量
clazz.getFields() 获取可见成员变量
clazz.getDeclaredFields() 获取所有成员变量(私有)
clazz.getField("") 获取指定可见成员变量
clazz.getDeclaredField("") 获取指定成员变量(私有)
③.方法
Class.getMethod(String,Class…paraTypes) 获取类中所有公有方法
Class.getDeclaredMethod(String,Class…paraTyoes) 获取类中所有方法(私有)
invoke(Object,Object…args) 调用该方法(赋值)
④.注解
getDeclaredAnnotations();或者getAnnotations();
method.getAnnotations();或
method.getDeclaredAnnotations(); 获取方法上的注解
field.getAnnotations();或
field.getDeclaredAnnotations(); 获取属性上的注解
四、注解
@Target
表示注解能写在什么上面,作用于哪里。
METHOD 可用于方法上
TYPE 可用于类或者接口上
FIELD 可用于属性上
PARAMETER 可用于参数上
CONSTRUCTOR 可用于构造方法上
ANNOTATION_TYPE 可用于注解类型上(被@interface修饰的类型)
LOCAL_VARIABLE 可用于局部变量上
PACKAGE 用于记录java文件的package信息
@Retention 保留
定义了该Annotation被保留的时间长短
1,仅出现在源代码中,而被编译器丢弃
2,被编译在class文件中

1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
@Documented 文档API
annotation应该被作为被标注的程序成员的公共API
@Inherited 被继承的
@Inherited阐述了某个被标注的类型是被继承的
@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类
自定义注解:
public @interface A {}
给注解定义属性:
权限 参数 属性名 默认 值
public String value() default “”;

注:权限只有public 和 默认的
参数支持的数据类型:
基本数据类型
String类型
Class类型,可以添加泛型
以及上面的数组类型

反射:
通过反射实例化User对象.
class User{
private int id;//id号
private String name; //用户名
private String password;//密码
//构造器和相应的set,get方法
public boolean checkName(String name){//实现代码}
public User getName(String name){//实现代码}
}
a)查询API查询该User对象包含哪些属性,属性的名字,访问修饰符等信息。
修改某个属性的值,获取某个属性的值。
b)查询API查询该User对象包含哪些方法,方法的名字,访问修饰符等信息。
通过反射调用某个方法。
c)查询API查询该User对象包含哪些构造器,构造器的名字,访问修饰符等信息。
通过反射调用构造器。

User类

  package com.briup.day12;
    public class User{
    	private int id;//id号
    	private String name; //用户名
    	private String password;//密码
    	private User user;
    	
public User() {
	super();
}
protected User(int id, String name, String password) {
	super();
	this.id = id;
	this.name = name;
	this.password = password;
}
//构造器和相应的set,get方法
public boolean checkName(String name){
	return false;
}
public User getName(String name){
	user=new User(1, name, "123");
	return user;
}
@Override
public String toString() {
	return "User [id=" + id + ", name=" + name + ", password=" + password
			+ ", user=" + user + "]";
}
}

UserTest类

package com.briup.day12;

import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import javax.swing.plaf.synth.SynthSeparatorUI;

public class UserTest {
	public static void main(String[] args) throws ClassNotFoundException {
		//获取class对象
		try {
			//镜像
			Class<?> class1 = Class.forName("com.briup.day12.User");
			Object instance = class1.newInstance();
			//获得所有成员变量(私有)
			Field[] fields = class1.getDeclaredFields();
			for(Field f:fields) {
				//获得属性的访问修饰符
				int modifiers = f.getModifiers();
				//获得属性的类型
				Class<?> type = f.getType();
				//获得属性的名字
				String name = f.getName();
				System.out.println(modifiers+" "+type+" "+name);
			}
			//获得指定成员变量(私有)
			Field field = class1.getDeclaredField("name");
			//通过反射修改某个属性的值,获取某个属性的值。
			field.setAccessible(true);//私有属性需要设置可见性
			field.set(instance, "zhangsan");
			
			
			Method[] methods = class1.getDeclaredMethods();
			for(Method m:methods) {
				//获得方法访问修饰符
				int modifiers = m.getModifiers();
				//获得方法的返回类型
				Class<?> type = m.getReturnType();
				//获得方法的名字
				String name = m.getName();
				//获得方法的参数类型
				Class<?>[] parameterTypes = m.getParameterTypes();
				System.out.println(modifiers+" "+type+" "+name+"("+parameterTypes+")"+parameterTypes.length);
			}
			//通过反射调用某个方法
			Method method = class1.getDeclaredMethod("getName", String.class);
			User user = (User)method.invoke(instance,"Lucy");
			
			Constructor<?>[] constructors = class1.getDeclaredConstructors();
			for(Constructor c:constructors) {
				int modifiers = c.getModifiers();
				String name = c.getName();
				Class[] types = c.getParameterTypes();
				System.out.println(modifiers+" "+name+"("+types+")");
			}
			//通过反射调用构造器
			Constructor<?> constructor = class1.getDeclaredConstructor(int.class,String.class,String.class);
			System.out.println(constructor.newInstance(3,"wangwu","123456"));
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值