注解,反射,常见语法糖

JAVA(注解,反射)

注解:Annotation,java标注,JDK5引入的机制

java中类,方法,变量,参数,

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@interface MyAnnotation{
    String name() default  "tom";
    int age();
}
public class Test1 {

    @MyAnnotation(name = "111",age = 20)
    public void run(){}

}

 

 元注解:

给注解加的注解

元注解有:@Retention,@Documented,@Target,@Inherited,@Repeatable5种

1.Retention

Rentention意思为保留期的意思,当他应用到一个注解上时,它解释说明了这个注解的存活时间

2.Documented

和文档有关,能将注解中的元素含到Javadoc中

3.Target

目标的意思,制定了注解运用的地方

4.Inherited

继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。

5.Repeatable

可重复的意思,是1.8的新特性

 

JAVA欲置的注解

@Deprecated

这个元素是用来标记过时的元素

@Override

提示重写父类被@Override修饰的方法

@SafeVarags

参数安全类型注解。它的目的是提醒开发者不要用参数做一些不安全的操作,它的存在会阻止编译器产生 unchecked 这样的警告。它是在 Java 1.7 的版本中加入的。

@FunctionalInterface

函数式接口注解,这个是 Java 1.8 版本引入的新特性。

 

注解中可以有方法

定义方法格式:String  name();

可以有默认值,也可以没有;若没有默认值,使用时必须加;需要默认值,deault添加

想使用时不指定具体名字,用value

 

在java整个的注解体系中,有三个主干类

1.Annotation 接口,定义一些方法

2.ElementType  枚举

  指定注解的类型,注解要用在哪里

3.RetentionPolicy  枚举

  指定注解的策略,不同策略指定作用域不同

  (1)SOURCE,注解仅存在于编译器处理期间

  (2)CLASS,注解在 .class文件中依然有效

  (3)RUNTIME,编译期不起作用,运行时才由jvm读取

 

反射

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。

 

反射的用处

反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但反射使用不当会造成很高的资源消耗。

 

反射的具体实现

有一个Person类

public class Person{
    //私有属性 
    private String name = "Tom";   
    //共有属性
    public int age = 18;
    //构造方法
    public Person(){}
    //私有方法
    private void say(){
        System.out.println("我是私有方法");
    }    
    //公有方法
    public void work(){
        System.out.print("我是公有方法");
    }    
}

 

得到class的三种方式

//1.通过对象调用getClass()方法获取
    Person p1 = new Person();
    Class c1 = p1.getClass();

//2.直接通过类名获得
    Class c2 = Person.class;

//3.通过Class对象 forName()静态方法获取
    Class c3 = Class.forName("com.fanshe.Person");

//注意:一个类中只有一个Class实例,上面的c1,c2,c3进行比较相等

 

Class的方法

例如

  getName():获得类的完整名字。
  getFields():获得类的public类型的属性。
  getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
  getMethods():获得类的public类型的方法。
  getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
  getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
  getConstructors():获得类的public类型的构造方法。
  getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
  newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

 

使用反射给对象属性赋值

/*获得一个类的字节码*/ 
    Class pClass = Class.forName("com.bjsxt.demo1.Person");
    Person person = (Person)pClass.newInstance();
    System.out.println(person);

/** 通过field对象完成给对象属性赋值 * */ 
    Field id = pClass.getDeclaredField("id"); 
    Field lastname = pClass.getDeclaredField("lastname");
    Field gender = pClass.getDeclaredField("gender"); 
    Field firstname = pClass.getDeclaredField("firstname"); 

// private修饰的属性不能直接 如果要使用先设置属性可以访问 
    id.setAccessible(true);
    lastname.setAccessible(true); 
    gender.setAccessible(true); 
    firstname.setAccessible(true); 

// 给属性赋值 id.set(person,1);
    lastname.set(person,"小明"); 
    gender.set(person,"男"); 

// 静态成员变量 不需要对象就可以赋值 
    firstname.set(null,"王"); 
    System.out.println(person);

 

使用反射调用对象方法

/*获得一个类的字节码*/
Class pClass = Class.forName("com.bjsxt.demo1.Person");
Constructor cons = pClass.getDeclaredConstructor(int.class, String.class, String.class);
Person person = (Person)cons.newInstance(1, "小明", "男"); 
// 1执行一个无参数无返回值的方法 
// 获取要调用的方法的Method对象 
Method showNameMethod = pClass.getDeclaredMethod("showName"); 
// 让method调用invoke方法 代表让当前方法执行 
// 如果是实例方法,在方法执行时,一定需要一个对象才行 
// 如果该方法执行需要参数,那么还要传入实参 
showNameMethod.invoke(person);
// 2如果执行一个有参数有返回值的方法 
// 那么需要在调用时传入实参 
Method sumMethod = pClass.getDeclaredMethod("sum", int.class, double.class);
// 设置方法时可以访问的 以免方法是private修饰造成方法不可方法 
sumMethod.setAccessible(true); 
double res=(double)sumMethod.invoke(person,1,3.14); 
System.out.println(res); 
// 3执行一个静态方法 
// 静态方法可以用对象去调用,也可以用类名去调用 
// 所以在执行静态方法是可以不传入对象 
Method setFirstname = pClass.getDeclaredMethod("setFirstname", String.class); 
setFirstname.invoke(null,"李");
System.out.println(person);

 

常见语法糖

Java 中最常用的语法糖主要有泛型、自动拆装箱、变长参数、枚举、内部类、增强 for 循环、try-with-resources 语法、lambda 表达式等

 

posted @ 2022-08-11 19:30  一只神秘的猫  阅读(57)  评论(0)    收藏  举报