注解,反射,常见语法糖
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 表达式等

浙公网安备 33010602011771号