Override –继承父类方法 且重写(覆盖)父类方法
表示当前方法覆盖父类的方法,可以保证编译时 •
候Override函数声明的正确性
只能用于方法 •
@Override
public void sayHello(){
System.out.println("老师好!");
}
Deprecated -表明方法已经过时
表示当前元素是不赞成使用的 •可以作用于类、属性、方法 •
@Deprecated
class Person{
@Deprecated
public String name;
@Deprecated
public void doSteal(){ //这个方法是不赞成使用的
System.out.println("偷东西是不对的!");
}
}
SuppressWarnings –
可以作用于一段代码
@SuppressWarnings("serial")
public class Test implements Serializable{
@SuppressWarnings("unchecked")
Set set = new HashSet();
@SuppressWarnings("unchecked")
public static void main(String[] args) {
@SuppressWarnings("unused")
List list = new ArrayList();
}
}
自定义注解
类似于新创建一个接口类文件,但为了区分,我们需要将它声 •
明为@interface。
说明:
注解中的每个方法实际上是声明了一个配置参数 –
方法的返回值要求是:基本类型、String、Class、枚 –
举、Annotation和它们组成的数组
另外,可用使用@Target、@Retention等限制自定义注解 –
[<修饰符>] @interface <注解名>{
返回值 方法名称() [<default value>];
返回值 方法名称() [<default value>];
……
}
元注解
元注解是指注解的注解。包括 @Retention @Target @Document •
@Inherited四种。
@Retention: 定义注解的保留策略
@Target:定义注解的作用目标
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
在Java编译器编译时,会识别在源代码里添加的注解是否还会 •
保留,这就是RetentionPolicy。编译器的处理有三种策略:
@Retention(RetentionPolicy.RUNTIME) –
表示JVM运行时此注解存在 •
@Retention(RetentionPolicy.CLASS) –
表示仅在class文件中存在,程序运行无法读取 •
@Retention(RetentionPolicy.SOURCE) –
表示仅在源文件中存在,编译之后会丢失
限制注解的使用范围
@Target: 表示该注解可以用于什么地方。可用ElementType枚 •
举类型主要有:
TYPE : 类、接口或enum声明 –
FIELD: 域(属性)声明 –
METHOD: 方法声明 –
PARAMETER: 参数声明 –
CONSTRUCTOR: 构造方法声明 –
LOCAL_VARIABLE:局部变量声明 –
ANNOTATION_TYPE:注释类型声明 –
PACKAGE: 包声明 –
自定义注解-示例
/*
* 自定义注解
*/@
Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
public enum FontColor {
BLUE, RED, GREEN
}i
nt id() default 100;
String info();
String[] names();
FontColor fontColor() default FontColor.RED;
}
public class MyAnnotationUsing {
@MyAnnotation(id = 1, info = "m1方法", names = { "zhangsan", "lisi" })
public void m1() {
}
@MyAnnotation(info = "m2方法", names = { "Tom", "Jerry" }, fontColor = FontColor.BLUE)
public void m2() {
}
}
/*
* 解析自定义注解
*/
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("com.neuedu.MyAnnotationUsing");
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ann = method.getAnnotation(MyAnnotation.class);
System.out.println(method.getName() + ": " + ann.id() + ", "
+ ann.info() + ", " + Arrays.toString(ann.names()) + "," + ann.fontColor());
}
}
}
在程序中读取注解信息,需要用到反射。 •
在系统中用到注解权限时非常有用,可以精确控制权限的 –
粒度
注意:要想使用反射去读取注解,必须将Retention的值选 –
为RetentionPolicy.RUNTIME
Java反射机制(Reflection)
在运行状态中,对于任意一个类,都能够知道这个类的所 –
有属性和方法;对于任意一个对象,都能够调用它的任意
一个属性和方法。
这种动态获取类的信息及动态调用对象方法的功能称 –
为java语言的反射机制。
反射机制提供的功能:在运行时获得类中各成员并使用它们 •
在运行时判断任意一个对象所属的类; –
在运行时构造任意一个类的对象; –
在运行时判断任意一个类所具有的成员变量和方法; –
在运行时调用任意一个对象的方法; –
生成动态代理。 –
四个核心类
Java反射机制的实现要借助于以下4个类 •
Class:类对象 –
下面三个组件都是通过Class获取的 •
Constructor:类的构造器对象 –
Field:类的属性对象 –
Method:类的方法对象 –
Class的获取及常用方法
// 1、获取类的类对象
Class<?> c_1 = Class.forName("com.Student");
// 2、获取对象的类对象
Student student = new Student();
Class<?> c_2 = student.getClass();
// 3、获取int的类对象
Class<?> c_3 = int.class;
// 4、获取包装类的类对象
Class<?> c_4 = Integer.TYPE;
Class的获取及常用方法
常用方法 •
forName(String className):返回与带有给定字符串名的类或接
口相关联的 Class 对象
getClassLoader() :返回该类的类加载器
getDeclaredAnnotations() :返回直接存在于此元素上的所有注解
getDeclaredConstructors() :返回类声明的所有构造方法
getDeclaredFields():返回类声明的所有字段,包括公共、保
护、默认(包)访问和私有字段,但不包括继承的字段
getDeclaredMethods() :返回类声明的所有方法,包括公共、保
护、默认(包)访问和私有方法,但不包括继承的方法
getName() :以 String 的形式返回此 Class 对象所表示的实体(
类、接口、数组类、基本类型或 void)名称
getPackage() : 获取此类的包
Constructor的获取及常用方法
Class<?> c = Class.forName("com.neuedu.Student");
// 本数组作为待查询构造器的参数(按顺序)
Class<?>[] objs = new Class[] { String.class, double.class }; Constructor<?> c_1 = c.getConstructor(objs);
Constructor<?>[] c_2 = c.getConstructors();
Constructor<?> c_3 = c.getDeclaredConstructor(objs);
Constructor<?>[] c_4 = c.getDeclaredConstructors();
常用方法 •
getName():以字符串形式返回此构造方法的名称
getModifiers():以整数形式返回此 Constructor 对象所表示构造方法的
Java 语言修饰符
getDeclaredAnnotations():返回直接存在于此元素上的所有注释
newInstance(Object... initargs) :使用此 Constructor 对象表示的构造方法
来创建该构造方法的声明类的新实例
实现反射机制的步骤
实现反射机制有以下三步 •
1、获得你想操作的类的 java.lang.Class 对象 –
2、获得你想操作的类的组件 –
(Constructor、Field、Method)或组件列表
3、使用反射的API来操作这些组件
实现反射机制的步骤
// 1、先获取 Student 的类对象
Class<?> c = Class.forName("com.Student");
// 2、构造类的实例,可以使用private的构造器
Constructor<?> constructor = c.getDeclaredConstructor(double.class,
boolean.class); // 获取到private构造器
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance(60, true); // score初始值设置为60
student.doStudy();
System.out.println();
// 3、调用方法,可以调用private的 doPlay()方法
// student.doPlay(); //直接使用,不能访问private方法
Method method = c.getDeclaredMethod("doPlay");
method.setAccessible(true); // 设置可以访问private方法
method.invoke(student);
Class[] cs = new Class[] { String.class, String.class };
Method method_2 = c.getDeclaredMethod("doEat", cs); // 调用有参有返回值的方法
String str = (String) method_2.invoke(student, "面包", "啤酒");
System.out.println(str);
System.out.println();
// 4、获取属性,可以获取private属性
// System.out.println(student.studyAtHome); //不能直接访问
Field field = c.getDeclaredField("studyAtHome");
field.setAccessible(true);
System.out
.println(field.getName() + " is " + field.getBoolean(student));
解析自定义注解
Class c = Class.forName("com.MyAnnotationUsing");
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ann = method.getAnnotation(MyAnnotation.class);
System.out.println(method.getName() + ": " + ann.id() + ", "
+ ann.info() + ", " + Arrays.toString(ann.names())
+ "," + ann.fontColor());
}
}