-----------------
反射
------------------------------------------------------------------------------------------------------------------------------
Java反射机制是在运动状态中,对于任意一个类都能知道这个类的所有属性和方法。
对于任意一个对象都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
简单说:反射就是将Java类中的各种成分映射成相应的java类。
反射的基石:Class类。
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类的类名就是Class。
获取Class对象的三种方式:
1.Object中的getClass方法。对象.getClass
例如:new Date().getClass();
2.任何数据类型都具备的静态属性。类名.class
例如:System.class
3.通过给定的类的字符串名称使用Class.forName()方法类获取该类。
例如:Class.forName("java.util.Date");
相关面试题: Class.forName()的作用。
作用是返回字节码文件,返回的方式有两种。
1.这份字节码曾经被加载过,已经在java虚拟机中,直接返回。
2.虚拟机中没有这份字节码,用类加载器加载。加载进的字节码缓存在虚拟机中。
九个预定义类型的实例对象:
基本的 Java 类型(boolean、byte、char、short、int、long、float 和double)和关键字void 也表示为Class对象。基本类型的字节码获取方式只有一种就是类名.class。例如int.class;void.class
数组也是一种Class的实例对象。
System.out.println(String.class.isPrimitive());//false
System.out.println(int.class.isPrimitive());//true
System.out.println(int.class == Integer.class);//false
System.out.println(int.class == Integer.TYPE);//true
System.out.println(int[].class.isPrimitive());//false
System.out.println(int[].class.isArray());//true
获取Class中的构造函数Constructor类:
得到某个类中所有的构造方法:
例子:Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
得到某个类中指定的构造方法:
Constructor construcor = Class.forName("java.lang.String").getConstructor(StringBuffered.class);
String str = (String)construcor.newInstance(new StringBuffered("abc"));
System.out.println(str.charAt(1));
Class.newInstance()方法。
例子:String str = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的空参构造方法,然后用该构造方法创建实例对象。
反射会导致性能下降。
获取Class中的字段Field类:
public class reflectPoint {
public int x ;
private int y;
public reflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
public class reflect1 {
public static void main(String[] args) throws Exception {
reflectPoint pt1 = new reflectPoint(3, 5);
// 通过getField()方法,获取公共的字段
Field fieldX = pt1.getClass().getField("x");
System.out.println(fieldX.get(pt1));
// 通过getDeclaredField(()方法获取私有方法
Field fieldY = pt1.getClass().getDeclaredField("y");
fieldY.setAccessible(true);//对私有字段取消访问权限,暴力访问。
System.out.println(fieldY.get(pt1));
}
}
获取Class中的方法。Method类代表某个类中的一个成员方法。
Method[] methods = Class.forName("java.lang.String").gerMethods();//获取公有方法。
methods = Class.forName("java.lang.String").gerDeclearedMethods();//获取私有的方法
String str = "abc";
Method methodcharAt = String.class.getMethod("charAt", int.class);
methodcharAt.invoke(str,1);//b
methodcharAt.invoke(str,new Object[]{2});//c
数组的反射:
具有相同维数和元素类型的数组,属于同一个类型,即具有相同的Class实例对象。
代表数组的class实例对象的getSuperClass()方法返回的父类为object类对应的class。
基本类型的额一维数组可以被当做object类型使用,不能当做Object[]类型使用。
非基本类型一维数组,及可以当做Object类型使用,又可以当做Object[]类型使用。
注意:Array.asList()方法处理int[]和String[]时的差异。
使用反射技术开发框架的原理:
反射的作用-->实现框架功能:因为在写程序时无法知道要被调用的类名,所以在程序中无法直接new某个实例对象,要用反射方式来获取。
框架与工具类的区别,工具类被用户的类调用,而框架则是调用用户提供的类。
-------------------------------------------------------------------------------------------------------------------------------------
注解
--------------------------
注解:
注解就是标注相当于一种标记,就像学生的胸卡,加上了注解就为程序打上了标记。
编译器,开发工具和其他程序来操作类和各种元素的时候可以根据注解做对应的处理。
注解的应用结构:
1.注解类型。
2.应用了注解类型的类。
3.对“应用了注解类型的类”进行反射操作的类
元注解:对注解类型进行注解的注解类型。(如元信息,描述信息的信息)
java的元注解都在java.lang.annotation包中,层次如下:
Annotation
|--Documented 指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。
|--Inherited 指示注释类型被自动继承。
|--Retention 指示注释类型的注释要保留多久。 (描述注释存在的周期)
|--Target 指示注释类型所适用的程序元素的种类 (描述注释存在的位置)
为注解增加基本属性。
增加属性的格式:
类型 变量名() default 变量实例 ; *
1.添加基本属性:类型为8个基本数据类型,String类,Class类,
2.添加高级属性:枚举,注解类型(注解类型也可以作为基本属性加个注解),
3.以上类型的数组。
注意:如果属性中只有一个value属性,或有多个属性,这些属性都用默认值,那么可以简写为: @Annotation(arg)(arg为value的值)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cn.itcast.day1.EnumTest;
/*
* .class文件不是字节码文件,class文件通过类加载器,进入内存后,内存中存在的才是字节码文件。
*/
@Retention(RetentionPolicy.RUNTIME)//Retention是元注解:对注解的注解
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
String color() default "red";
String value();
int[] arrayAttri() default {1,2,3};
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;
MetaAnnotation annoAttr() default @MetaAnnotation("yxf");
}