注解
- Annotation的作用:
- 不是程序本身,可以对程序作出解释(这一点和注释(comment)没什么区别)
- 可以被其他程序(例如:编译器等)读取
- Annotation的格式
- Annotation在哪里使用
- 我们可以在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问
内置注解
- @Override
- @Deprecated 不推荐程序员使用,或者存在更好的方式
- @SuppressWarnings(“all”)
元注解
- 元注解(meta-annotation)的作用就是负责注解其他注解
- @Target
- @Retention(SOURCE<CLASS<RUNTIME)
- @Documented
- @Inherited
@MyAnnotation
public class Demo2 {
@MyAnnotation
public void test(){
}
}
//@Target 表示我们的注解可以用在哪些地方
//@Retention 表示我们的注解在什么地方还有效
//@Documented 表示是否将我们的注解生成在Javadoc中
//@Inherited 子类可以继承父类的注解
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface MyAnnotation{
}
自定义注解
- public @interface 注解名{定义内容}
- 其中的每一个方法实际上声明了一个配置参数
- 方法的名称实际上就是参数的名称
- 返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)
- 可以通过default来声明参数的默认值
- 如果只有一个参数成员,一般参数名为value
- 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值
//自定义注解
public class Demo3 {
//注解可以显示赋值,如果没有默认值,必须赋值
@MyAnno(name = "szx",schools = {"hd","hlg"},age = 18)
public void test(){
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno{
//注解的参数:参数类型 参数名();
String name() default "";
int age() default 0;
int id() default -1;//如果默认值-1代表不存在
String[] schools();
}
反射机制
- Reflection是Java被视为动态语言的关键,反射机制允许程序在执行期借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
- 正常方式:引入需要的“包类”名称–>通过new实例化–>取得实例化对象
- 反射方式:实例化对象–>getClass()方法–>得到完整的“包类”名称
- 优点:
- 缺点:
Class类
- Class本身也是一个类
- Class对象只能由系统建立对象
- 一个加载的类在JVM中只会有一个Class实例
- 一个Class对象对应的是一个加载到JVM中的一个.class文件
- 每个类的实例都会记得自己是由哪个Class实例所生成
- 通过Class可以完整得到一个类中的所有被加载的结构
- Class类是Reeflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class类
- 获取Class类实例:
- 通过调用类.class
- 利用对象调用getClass()方法获取该对象的Class实例
- 使用Class类的静态方法forName(),用类的名字获取一个Class实例(static Class forName(String className) ),这种方式灵活性最高,根据类的字符串全名即可获取Class实例,可以动态加载类,框架设计经常用到
public class Demo5 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是:"+person.name);
Class<? extends Person> c1 = person.getClass();
Class<?> c2 = Class.forName("com.annotation.Student");
Class<Student> c3 = Student.class;
//获得父类类型
Class<?> superclass = c1.getSuperclass();
System.out.println(superclass);
}
}
public class Demo7 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class<?> c1 = Class.forName("com.annotation.User");
//获得类的名字
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
//获得类的属性
Field[] fields1 = c1.getFields();//只能找到public属性
Field[] fields = c1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
//获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
System.out.println("--------------------------------------------------");
//获得类的方法
Method[] declaredMethods = c1.getDeclaredMethods();//获得本类的所有方法
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("--------------------------------------------------");
declaredMethods = c1.getMethods();//获得本类及父类的所有public方法
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
Method setName = c1.getMethod("setName", String.class);
System.out.println(setName);
}
}
- 通过反射,动态的创建对象
- Method Constructor,Field都有setAccessible()方法
- 作用是启动(false)和禁止(true)访问安全检测的开关
- 默认 false
- 安全检测会降低效率
- 普通方式效率比反射快
public class Demo8 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得class对象
Class<?> c1 = Class.forName("com.annotation.User");
//构造一个对象
//User user = (User) c1.newInstance();//本质调用了类的无参构造器
//System.out.println(user);
//通过构造器创建对象
// Constructor<?> constructor = c1.getConstructor(String.class, int.class, int.class);
// Object user2 = constructor.newInstance("su", 111, 18);
// System.out.println(user2);
//通过反射调用普通方法
User user3 = (User) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke 激活 (对象,方法值)
setName.invoke(user3,"szx");
System.out.println(user3.getName());
//通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,需要关闭程序安全检测
name.setAccessible(true);
name.set(user4,"a");
System.out.println(user4.getName());
}
}
反射操作泛型
public class Demo9 {
public void test01(Map<String,User> map, List<User> list){
System.out.println("test01");
}
public Map<String,User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = Demo9.class.getMethod("test01", Map.class, List.class);
Type[] gpt = method.getGenericParameterTypes();
for (Type type : gpt) {
System.out.println(type);
if (type instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("真实"+actualTypeArgument);
}
}
}
Method method1 = Demo9.class.getMethod("test02", null);
Type type = method1.getGenericReturnType();
if (type instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
反射操作注解
//练习反射操作注解
public class Demo10 {
public static void main(String[] args) throws Exception {
Class<?> c1 = Class.forName("com.annotation.Stu");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解value值
Table table = (Table) c1.getAnnotation(Table.class);
System.out.println(table.value());
//获得类指定的注解
java.lang.reflect.Field f = c1.getDeclaredField("name");
Field annotation = f.getAnnotation(Field.class);
System.out.println(annotation.columName());
System.out.println(annotation.length());
System.out.println(annotation.type());
}
}
@Table("db-stu")
class Stu{
@Field(columName = "id",type = "int",length = 10)
private int id;
@Field(columName = "age",type = "int",length = 10)
private int age;
@Field(columName = "name",type = "varchar",length = 3)
private String name;
public Stu() {
}
public Stu(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Stu{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
String columName();
String type();
int length();
}