1)对程序的解释说明
2)可以通过外部的工具获取程序的信息并进行操作
@注解名 位置:可以在任意位置,不同的注解可以使用的位置可能不同
(1)标记注解:一个参数都没有
(2)单值注解:只有一个参数
(3)完整注解:多个参数
a.@Override 检查重写
b.@SuppressWarnings(“all”) 抑制警告
c.@Deprecated 标志过时
a.@Target : 决定这个注解类可以使用在哪些位置
@Target({ElementType.METHOD , ElementType.TYPE})//这个注解可以加在方法和类上
b.@Retention :注解的声明周期
@Retention元注解,决定注解使用的时期,有三个取值,
RetetionPolicy.SOURCE、RetetionPolicy.CLASS、Retetion.RUNTIME,分别对应
java源文件--------------------------->class文件-------------->内存中的字节码
c.@Documented : api文档 javadoc 能够存在与对应的这个类的api文档中
d.@Inherited : 被继承的注解
@SuppressWarnings("all")
public class AnnoDemo01 {
@SuppressWarnings("all")
public static void main(String[] args) {
//@SuppressWarnings("all") //抑制警告
List ls=new ArrayList();
List ls2=new ArrayList();
test();
}
@Deprecated
static void test(){
List ls=new ArrayList();
}
}
class Fu{
void test(){}
}
class Zi extends Fu{
@Override
void test(){}
}
@FunctionalInterface
interface A{
void test();
}
@interface 自定义注解类
注意:
a. 注解类只能被public 和 default修饰
b.注解类中定义字段,字段名()
c.注解中的字段的数据类型:基本数据类型,字符串,注解,枚举,以及这些类型的数组
d. 定义字段时,如果只有一个字段,建议字段名起为value,这value赋值时候可以省略,如果多个字段不可以省略
@Target(value={ElementType.TYPE})可以省略value=部分,
由于数组只有一个元素,所以可以 省略大括号。简写成@Target(ElementType.TYPE)
e. 字段可以设置默认值 使用default关键字
//@MyAnno(name="张三",age=121)
@MyAnno(false)
public class AnnoDemo02 {
//@MyAnno(age=13,name="haha")
public static void main(String[] args) {
}
}
//自定义直接类
@Target({TYPE,METHOD})
@Retention(RetentionPolicy.RUNTIME)
//@Documented
@Inherited
@interface MyAnno{
// String name();
int age() default 1;
boolean value();
}
class Haha extends AnnoDemo02{
}
在一个类加载的时候,在内存中就会存在一个这个类的Class对象,
Class对象中存着这个类的一切信息(类,构造器,方法,属性…)
一个类只有一个Class对象
在创建对象的时候,其实是获取了一个这个类型的Class对象的一个镜像|复制体
如果能够获取到这个类的Class对象,就可以做一切操作!!!
1)对象.getClass()
2)类名.class
3)Class.forName(权限定名) :包名+类名
①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理。
public class ReflectDemo03 {
public static void main(String[] args) throws ClassNotFoundException {
//对象.getClass()
Class cls1="你好".getClass();
Class cls2="哈哈".getClass();
System.out.println(cls1==cls2);
//类名.class
Class cls3=String.class;
System.out.println(cls3==cls1);
//Class.forName(权限定名) :包名+类名
Class cls4=Class.forName("java.lang.String");
System.out.println(cls4==cls2);
//子类的Class对象.getSuperclass() 获取父类的Class对象
Class cl5=cls4.getSuperclass();
Class cls6=Class.forName("java.lang.Object");
System.out.println(cl5==cls6);
}
static void test() throws ClassNotFoundException{
Class.forName("com.shsxt.Apple");
}
}
Class类中的一系列方法
java.lang.reflect.Modifier
public static final int ABSTRACT 1024
public static final int FINAL 16
public static final int INTERFACE 512
public static final int NATIVE 256
public static final int PRIVATE 2
public static final int PROTECTED 4
public static final int PUBLIC 1
public static final int STATIC 8
public static final int STRICT 2048
public static final int SYNCHRONIZED 32
public static final int TRANSIENT 128
public static final int VOLATILE 64
1).Constructor getConstructor(Class>… parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
2).Constructor>[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
以上两个只能获取到公共的构造器!!!
3).Constructor getDeclaredConstructor(Class>… parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
4).Constructor>[] getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
以上两个只能获取到所有权限的构造器包括私有!!!
5).使用构造器创建对象,通过反射的方式
Class–> newInstance() 创建此 Class 对象所表示的类的一个新实例。 调用这个类的空构造,如果使用,必须确保存在空构造
6).Constructor–> newInstance(Object… initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
public final class ReflectDemo04 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// getSuper(User.class);
getCons(User.class);
}
public static void getCons(Class cls) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
// Constructor con=cls.getConstructor(String.class);
// System.out.println(con);
/*Constructor[] arr=cls.getConstructors();
for(Constructor c:arr){
System.out.println(c);
}*/
Constructor<User> con=cls.getDeclaredConstructor(String.class,int.class);
System.out.println(con);
/*Constructor[] arr=cls.getDeclaredConstructors();
for(Constructor c:arr){
System.out.println(c);
}*/
//创建对象1
User u=(User) cls.newInstance();
System.out.println(u);
//创建对象2
User u2=con.newInstance("哈哈",1);
System.out.println(u2.getName()+"-->"+u2.getAge());
}
/*
* 测试父接口,父类
*/
public static void getSuper(Class cls) throws ClassNotFoundException{
//获取一个父类的Class对象
Class superClass=cls.getSuperclass();
//所有实现的接口的Class对象
Class[] arr=cls.getInterfaces();
for(Class c:arr){
System.out.println(c);
}
int i=cls.getModifiers();
System.out.println(i); //修饰符的int值为多个修饰符的和
System.out.println(Modifier.toString(i)); //以字符串的形式打印修饰符
/*
* String getName()
以 String 的形式返回此 Class 对象所表示的实体
*/
System.out.println(cls.getName()); //包名+类名
/*
* Package getPackage()
获取此类的包。
*/
System.out.println(cls.getPackage().getName());
/*
* String toString()
将对象转换为字符串。
*/
System.out.println(cls.toString());
/*
* boolean isPrimitive()
判定指定的 Class 对象是否表示一个基本类型。
*/
//基本数据类型获取Class对象
Class pri=int.class;
Class pri4=Integer.TYPE; //Type属性可以获取对应的基本数据类型的Class对象
Class pri5=Double.TYPE;
Class pri2=Integer.class;
Class pri3=Class.forName("java.lang.Integer");
System.out.println(pri);
System.out.println(pri.isPrimitive());
System.out.println(pri2.isPrimitive());
System.out.println("pri3:"+pri3.isPrimitive());
System.out.println("pri4:"+pri4.isPrimitive());
System.out.println("pri5:"+pri5.isPrimitive());
System.out.println(cls.isPrimitive());
System.out.println(pri3.toString());
}
}
interface B{}
class Person{}
/**
* @author yana
*
*/
class User extends Person implements B{
private String name;
private int age;
double salary;
public User(String name, int age, double salary) {
super();
this.name = name;
this.age = age;
this.salary = salary;
}
public User(String name) {
// TODO Auto-generated constructor stub
}
private User(double salary){
}
User(String name,int age) {
this.name=name;
this.age=age;
}
public User() {
System.out.println("hhhhhhhh");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", salary=" + salary + "]";
}
}
public static void getField(Class cls) throws Exception{
Field[] fls=cls.getDeclaredFields();
for(Field f:fls){
System.out.println(f);
}
//创建一个User对象
User u=(User) cls.newInstance();
//属性设置值
fls[2].set(u, 20000.0);
System.out.println(u.getSalary());
System.out.println(fls[2].get(u));
fls[0].setAccessible(true);
fls[0].set(u, "夏魁文");
System.out.println(u.getName());
fls[0].setAccessible(false);
}
a.Method getMethod(String name, Class>… parameterTypes)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
b.Method[] getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由 该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
a.Method getDeclaredMethod(String name, Class>… parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
b.Method[] getDeclaredMethods()
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
c.Method -->Object invoke(Object obj, Object… args)
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
public static void getM(Class cls) throws Exception{
Method[] ms=cls.getMethods();
for(Method m:ms){
System.out.println(m);
}
Method me=cls.getDeclaredMethod("testDe", int.class);
System.out.println(me);
//创建一个User对象
User u=(User) cls.newInstance();
//私有方法没有权限操作--->开放权限
me.setAccessible(true); //开放
//执行方法
me.invoke(u, 100);
me.setAccessible(false); //开放
}
public class ReflectDemo06 {
public static void main(String[] args) {
/*
* static Object newInstance(Class> componentType, int length)
创建一个具有指定的组件类型和长度的新数组。
*/
int[] o=(int[]) Array.newInstance(Integer.TYPE, 8);
System.out.println(o.length);
Class cls=o.getClass();
//判断是否为数组
System.out.println(cls.isArray());
Array.set(o, 0, 100);
Array.set(o, 2, 102);
Array.set(o, 4, 104);
System.out.println(Arrays.toString(o));
System.out.println(Array.get(o, 4));
}
}
public class ReflectDemo07 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
Class cls=Demo.class;
Annotation[] arr=cls.getAnnotations();
System.out.println(Arrays.toString(arr));
System.out.println(arr[0].annotationType()); //com.shsxt.ref02.MyAnno包名+类名
//boolean isAnnotationPresent(Class extends Annotation> annotationClass) 如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
System.out.println(cls.isAnnotationPresent(MyAnno.class));
//字段上的注解
Field f=cls.getDeclaredField("haha");
/*
* T extends Annotation>
getAnnotation(Class annotationClass)
如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
*/
MyAnno a=f.getAnnotation(MyAnno.class);
System.out.println(a.age());
System.out.println(a.name());
/*
* 操作方法的注解
*/
Method m=cls.getDeclaredMethod("test", String.class);
/*
* Annotation[] getDeclaredAnnotations()
返回直接存在于此元素上的所有注释
*/
Annotation[] an=m.getDeclaredAnnotations();
/*
* Annotation[][] getParameterAnnotations()
返回表示按照声明顺序对此 Method 对象所表示方法的形参进行注释的那个数组的数组。
*/
Annotation[][] arr2=m.getParameterAnnotations();
System.out.println(Arrays.deepToString(arr2));
System.out.println(((MyAnno)arr2[0][0]).age());
}
}
@Target({TYPE,METHOD,FIELD,PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface MyAnno{
String name();
int age();
}
@MyAnno(name="张三",age=19)
@SuppressWarnings("all")
class Demo{
@MyAnno(name="李四",age=20)
String haha;
void test(@MyAnno(name="heihei",age=1) String a){
}
}
}
相当于一种标记,在程序中加入注解就等于为程序打上某种标记**,没有加,则等于没有任何标记,以后,javac编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无何种标记,看你的程序有什么标记,就去干相应的事,标记可以加在包、类,属性、方法,方法的参数以及局部变量上。
运行期间可以通过获取Class对象进行一系列操作
获取Class对象
(1)Class: 通过Class对象获取到一下系列类的对象
(2)Method :执行 invoke(对象,参数值…) 静态方法invoke(null,参数值…)
(3)Constructor :创建对象
(4)Field : 设置set() 获取get()
(5)Modifier : toString 获取这个对象上的修饰符->int和
(6)Array:创建 newInstance(类型,长度) set(obj,index,value) get(obj,index)
(7)以上类中都有操作反射的方法,强转…获取到对应的某个注解类的对象,调用注解类中的字段值