Annotation是从JDK5.0开始引入的新技术
/ / @Override重写的注解
@Override
public string toString() {//注意方法签名要一致,如果改成Test01会报错
return super.toString();
}
元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明
这些类型和它们所支持的类在java.lang.annotation包中可以找到(@Target , @Retention,@Documented , @lnherited )
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
分析:
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键
静态VS 动态语言
在Object类中定义了以下的方法,此方法将被所有子类继承
以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息。
a)若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高。
Class clazz= Person.class;
b)已知某个类的实例,调用该实例的getClass()方法获取Class对象
Class clazz = person.getClass();
c)已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException异常
Class clazz=Class.forName("demo01.Student");
d)内置基本数据类型可以直接用类名.Type
e)还可以利用ClassLoader我们之后讲解
//测试class类的创建方式有哪些
public class Test03 {
public static void main(String[] args) throws classNotFoundException {
Person person = new Student();
System.out.println("这个人是:"+person.name) ;
//方式一:通过对象获得
Class c1 = person.getClass( );
//方式二 : forname获得
Class c2 = Class.forName ( "com.kuang.reflection. Student");
//方式三:通过类名.class获得
Class c3 = Student.class;
//方式四∶基本内置类型的包装类都有一个Type属性
Class c4 = Integer.TYPE;
//获得父类类型
Class c5= c1.getSuperclass();
}
class Person{
public string name ;
有参、无参、tostring...;
}
class Student extends Person{
public Student(){
this.name ="学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name ="老师";
}
}
//所有类型的class
public class Test04 {
public static void main(string[] args) {
Class c1 = Object.class; //类
Class c2 = Comparable.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; //void
Class c9 = Class.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);
//只要元素类型与维度一样,就是同一个class.
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象.
链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。
初始化:
public class Test05 {
public static void main(string[] args) {
A a = new A();
System.out.println(A.m);
}
}
class A{
static {
System.out.println( "A类静态代码块初始化");
m = 300;
}
static int m = 100;
public A() {
System.out.println("A类的无参构造初始化");
}
}
类的主动引用(一定会发生类的初始化)
类的被动引用(不会发生类的初始化)
//测试类什么时候会初始化
public class Test06 {
static {
System.out.println ("Main类被加载");
}
public static void main(string[] args) {
//主动引用
Son son = new Son();//结果一
//反射也会产生主动引用
Class.forName ("com.kuang.reflection.Son");//结果一
//不会产生类的引用的方法
System.out.println(Son.b);//结果二
Son[] array = new Son[5];//结果三
}
}
class Father{
static int b = 2 ;
static {
System.out.println("父类被加载");
}
}
class son extends Father{
static {
System.out.println("子类被加载");
m = 300;
}
}
通过反射获取运行时类的完整结构
Field字段、Method方法、Constructor构造器、Superclass父类、Interface接口、Annotation注解
//获得类的信息
public class Test{
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName ("com.kuang.reflection.User");
//获得类的名字
System.out.println(c1.getName()); //获得包名+类名
System.out.println(c1.getSimpleName());//获得类名
//获得类的属性
Field[] fields = c1.getFields(); //只能找到public属性
fields = c1.getDeclaredFields(); //找到全部的属性
for (Field field : fields) {
System.out.println(field);
}
//获得指定属性的值
Field name = c1.getDeclaredField("name");
//获得类的方法
Method[] methods = c1.getMethods();//获得本类及其父类的全部public方法
for (Method method : methods) {
System.out.println("正常的:"+method);
}
methods = c1.getDeclaredMethods();//获得本类的所有方法
for (Method method : methods) {
System.out.println("getDeclaredMethods: "+method);
}
//获得指定方法
//重载
Method getName = c1.getMethod("getName",null);
Method setName = c1.getMethod("setName",String.class);
System.out.println(getName);
System.out.println(setName);
//获得指定的构造器
Constructor[] constructors = c1.getConstructors();
for(Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();
for (constructor constructor : constructors){
System.out.println(""#""+constructor);
}
//获得指定的构造器
Constructor declaredConstructor =
c1.getDeclaredConstrultor(String.class,int.class,int.class);
System.out.println("指定: "+declaredConstructor);
}
}
有了Class对象,能做什么?
创建类的对象:调用Class对象的newlnstance()方法
思考?难道没有无参的构造器就不能创建对象了吗?只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作。
步骤如下:
调用指定的方法
通过反射,调用类中的方法,通过Method类完成。
Object invoke(Object obj, Object ... args)
setAccessible
//获得class对象
Class c1 = Class.forName ("com.kuang.reflection.User");
//构造一个对象
User user = (User)c1.newInstance(); //本质是调用了类的无参构造器
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
User user2 = (User)constructor.newInstance("JANE",001,18);
//通过反射调用普通方法
User user3 =(User)c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName",String.class);
//invoke :激活的意思
//(对象,"方法的值")
setName.invoke(user3,"dany");
System.out.println(user3.getName());
//通过反射操作属性
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true)
name.setAccessible(true);
name.set(user4,"Liming");
System.out.println(user4.getName());
public class Test11 {
//没有返回值
public void test01(Map map,List list){
System.out.println("test01");
}
//有返回值
public Map test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = Test11.class.getMethod("test01",Map.class,List.class);
//获得泛型的参数类型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes){
System.out.println( "#""+genericParameterType);
//泛型的参数类型是否是参数化类型
if (genericParameterType instanceof ParameterizedType){
//强转获得真实参数信息
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for ( Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
method = Test11.class.getMethod("test02",null) ;
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).
getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
@Tablekuang ( "db_student")
class student2{
@Fieldkuang(columnName = "db_id", type = "int" , length = 10)
private int id;@Fieldkuang(columnName = "db_age", type = "int" , length = 10)
private int age;
@Fieldkuang(columnName = "db_name", type = "varchar" , length =3)
private String name;有参无参、setget、tostring...
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)@interface Table{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy. RUNTIME)@interface Field{
String columnName( );String type();
int length( );}
//练习反射操作注解
public class Test{
public static void main(string[] args) throws classNotFoundException {
Class c1 =Class.forName ( "com.reflection.student2");//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();for (Annotation annotation : annotations) {
System.out.println( annotation);//结果com.kuang.reflection.Tablekuang(value=db_student)
}
//获得注解的value的值。
Table table = (Table)c1.getAnnotation(Table.class);String value = table.value();
System.out.println(value) ;//结果db_student
//获得类字段指定的注解
Field f = c1.getDeclaredField("name" ) ;
Field annotation = f.getAnnotation(Field.class);System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length() );}