注解(java.Annotation) 概念 注解和注释一样,注解不是程序本身,而是对程序作出解释,而注解与注释不同的点在于,注解可以被其他程序比如编译器读取。
下面列举三个基本常见的注解:
1 2 3 @Override @Deprecated @SuppressWarnings
元注解 元注解的作用解释注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型做说明。
4个元注解分别为:
@Target:用于描述注解的使用范围
@Retention:用于表示需要在什么级别保存注解信息,用于描述注解的声明周期,(SOURCE<CLASS<RUNTIME)
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package SunAnnotation;import java.lang.annotation.*;@MyAnnotation public class Annotation_01 { public void test () { } } @Target(value ={ ElementType.METHOD,ElementType.TYPE}) @Retention(value = RetentionPolicy.RUNTIME) @Documented @Inherited @interface MyAnnotation{}
自定义注解 使用@interface自定义注解时﹐自动继承了java.lang.annotation.Annotation接口
分析:
interface用来声明一个注解,格式:public @interface注解名{定义内容}
其中的每一个方法实际上是声明了一个配置参数.
方法的名称就是参数的名称.
返回值类型就是参数的类型人(返回值只能是基本类型.Class , string , enum ).
可以通过default来声明参数的默认值.
如果只有一个参数成员,一般参数名为value.
注解元素必须要有值﹐我们定义注解元察时,经常使用空字符串,0作为默认值.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package SunAnnotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;public class Annotation_02 { @MyAnnotation1(schools = "FJUT") public void test1 () { } @MyAnnotation2("小明") public void test2 () { } } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation1{ String name () default "" ; int age () default 0 ; int id () default -1 ; String[] schools(); } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ String[] value(); }
反射(java.Reflection) 动态语言和静态语言 动态语言 : 在运行时可以改变其结构:例如新的函数、对象甚至代码可以被引进,已有的函数可以被删除或者是其他结构上的变化。通俗来说就是运行时代码可以根据一些条件来改变自身的结构。主要动态语言:Object-C、C#、JavaScript、PHP、Python等。
静态语言 : 与动态语言相对应的,运行时不能改变其结构,如Java、C、C++。Java不是动态语言,但是java可以称为是“准动态语言”。即java有一定的动态性,可以利用反射机制获得类似动态语言的特性。Java的动态性使得编程时更加灵活。
java.Reflection应用: 反射是Java被视为动态语言的关键,反射机制允许程序在执行期间借助于ReflectionAPI获取任何类的内部信息,并且能够直接操作任意对象的内部属性及方法。
加载完类之后,在堆内存中的方法区中间产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 package SunReflection;public class Reflection_01 { public static void main (String[] args) throws ClassNotFoundException { Class c1 = Class.forName("SunReflection.User" ); Class c2 = Class.forName("SunReflection.User" ); Class c3 = Class.forName("SunReflection.User" ); System.out.println(c1); System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); } } class User { private String name; private int Id; public User () { } public User (String name, int id) { this .name = name; Id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getId () { return Id; } public void setId (int id) { Id = id; } @Override public String toString () { return "User{" + "name='" + name + '\'' + ", Id=" + Id + '}' ; } }
Class类的常用方法
方法名
说明
static Class forName(String name)
返回指定类名name对应的Class对象
Object newInstance()
调用缺省构造函数,返回Class对象的一个实例
String getName()
返回此Class对象所表示的实体(类、接口、数组类或者void)的名称
Class getSuperClass
返回当前Class对象的父类Class对象
Class[] getinterfaces()
获取当前Class对象的接口
ClassLoader getClassLoader()
返回该类的加载器
Constructor[] getConstructors()
返回一个包含某些Constructor对象的数组
Method getMothed(String name,Class… T)
返回一个Method对象,此对象形参类型为param Type
Fied[] getDeclaredFields()
返回Field对象的一个数组
获得类的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package SunReflection;public class Reflection_02 { public static void main (String[] args) throws ClassNotFoundException { Person person = new Student (); System.out.println("这个人是:" +person.name); Class c1 = person.getClass(); System.out.println(c1.hashCode()); Class c2 = Class.forName("SunReflection.Student" ); System.out.println(c2.hashCode()); Class c3=Student.class; System.out.println(c3.hashCode()); Class c4=Integer.TYPE; Class c5 = c1.getSuperclass(); System.out.println(c5); } } class Person { public String name; public Person () { } public Person (String name) { this .name = name; } @Override public String toString () { return "Person{" + "name='" + name + '\'' + '}' ; } } class Student extends Person { public Student () { this .name="学生" ; } } class Teacher extends Person { public Teacher () { this .name="老师" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package SunReflection;import java.lang.annotation.ElementType;public class Reflection_03 { public static void main (String[] args) { Class c1= Object.class; Class c2= Runnable.class; Class c3= String[].class; Class c4= int [][].class; Class c5=Override.class; Class c6= ElementType.class; Class c7= Integer.class; Class c8= void .class; Class c9= Class.class; System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9); } }
注意:
同样是int类型的数组,维度不同Class对象所打印出的hashcode不同,即:数组维度不同对应不同的Class对象。
获取运行时类的完整结构 Field、Method、Constructor、Superclass、Interface、Annotation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package SunReflection;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Reflection_04 { public static void main (String[] args) throws Exception { Class<User> userClass = User.class; System.out.println(userClass.getName()); System.out.println(userClass.getSimpleName()); System.out.println("-----------------------------------------" ); Field[] field1 = userClass.getFields(); for (Field f :field1) { System.out.println(f); } Field[] field2=userClass.getDeclaredFields(); for (Field f :field2) { System.out.println(f); } Field name = userClass.getDeclaredField("name" ); System.out.println(name); System.out.println("--------------------" ); Method[] methods = userClass.getMethods(); for (Method method:methods) { System.out.println("1" +method); } methods=userClass.getDeclaredMethods(); for (Method method:methods) { System.out.println("2" +method); } System.out.println("-------------------------" ); Constructor[] constructors=userClass.getConstructors(); for (Constructor c :constructors) { System.out.println("#" +c); } constructors=userClass.getDeclaredConstructors(); for (Constructor c :constructors) { System.out.println("$" +c); } System.out.println(userClass.getDeclaredConstructor(String.class)); } }
创建运行时类的对象 创建类的对象
调用Class对象的newInstance()方法
必须要有一个无参数的构造器
类的构造器的访问权限要够
通过获取Class对象的构造器创建
通过Class对象的getDeclaredConstructor()方法获取本类指定参数类型的构造器(上一节有讲)
向构造器传入一个对象数组,其中包含此构造器所需要的各个参数
通过Constructor实例化对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package SunReflection;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Reflection_05 { public static void main (String[] args) throws Exception{ Class<User> c1 = User.class; User user = c1.newInstance(); System.out.println(user); Constructor<User> constructor = c1.getDeclaredConstructor(String.class, int .class); User user1 = constructor.newInstance("小明" , 18 ); System.out.println(user1); System.out.println("=============================================" ); User user3 = (User) c1.newInstance(); Method setName = c1.getDeclaredMethod("setName" , String.class); setName.setAccessible(true ); setName.invoke(user3,"China" ); System.out.println(user3.getName()); System.out.println("=============================================" ); User user4 = (User) c1.newInstance(); Field name = c1.getDeclaredField("name" ); name.setAccessible(true ); name.set(user4,"李四" ); System.out.println(user4.getName()); } }
不同方式调用方法性能测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package SunReflection;import javax.swing.plaf.synth.SynthOptionPaneUI;import java.lang.reflect.Method;public class Reflection_06 { public static void test01 () { User user = new User (); long startTime=System.currentTimeMillis(); for (int i = 0 ; i < 1000000000 ; i++) { user.getName(); } long endTime=System.currentTimeMillis(); System.out.println("直接调用执行10亿次需要:" +(endTime-startTime)+"ms" ); } public static void test02 () throws Exception{ User user = new User (); Class<User> c1 = User.class; Method getName = c1.getDeclaredMethod("getName" , null ); long startTime=System.currentTimeMillis(); for (int i = 0 ; i < 1000000000 ; i++) { getName.invoke(user,null ); } long endTime=System.currentTimeMillis(); System.out.println("反射方式调用执行10亿次需要:" +(endTime-startTime)+"ms" ); } public static void test03 () throws Exception{ User user = new User (); Class<User> c1 = User.class; Method getName = c1.getDeclaredMethod("getName" , null ); long startTime=System.currentTimeMillis(); getName.setAccessible(true ); for (int i = 0 ; i < 1000000000 ; i++) { getName.invoke(user,null ); } long endTime=System.currentTimeMillis(); System.out.println("反射方式调用,关闭安全监测调用执行10亿次需要:" +(endTime-startTime)+"ms" ); } public static void main (String[] args) throws Exception{ test01(); test02(); test03(); } }