十二: 反射
利用类加载时在堆中创建的java.lang.Class对象去获得该类加载以后在方法区中创建的类信息,方法信息,变量信息...
12.1 : Class c = Class.forName("[类全包名+类名]/[全限定名]");//通过类加载器加载全限定名所对应的类.--->类加载--->涉及到 内存问题.回顾 2.5
作用:利用该类的Class对象可以创建对象,访问属性,访问方法,访问构造器
12.2 : 创建对象: c.newInstance();
12.3 : 获得属性镜像: Field field = c.getField("属性名");
Field[] fields = c.getFields();
Field[] fields = c.getDeclaredFields();
12.4 : 获得方法镜像: Method method = c.getMethod("方法名",参数1.class,参数2.class...);
Method method = c.getDeclaredMethod("方法名",,参数1.class,参数2.class...);
如果是私有属性需要设置可见性:method.setAccessible(true);
设置可见性: Method.setAccessible(methodarray, flag);
12.4.1:利用方法镜像调用目标对象的方法:
Object returnValue = method.invoke(obj, args...);
12.4.2:利用方法镜像获得方法的返回值类型
method.getGenericReturnType();
12.4.3:利用方法镜像获得方法的修饰符
method.getModifiers()
12.4.4:利用方法镜像获得方法名
method.getName();
12.4.5:利用方法镜像获得方法的参数列表
method.getGenericParameterTypes();
12.4.6:利用方法镜像获得方法的异常
method.getGenericExceptionTypes();
注意:method,是一个方法的镜像,只能对应一个方法。
12.5 : 获取构造器镜像:Constructor<?>[] constructors = c.getConstructors();
Constructor<?> constructor2 = c.getConstructor(参数1.class,参数1.class,...);
12.5.1:利用构造器镜像 创建对象
constructor.newInstance(参数,参数,...);//用有参构造器创建对象
注意:反射创建对象有两种方式:
1,直接用class.newInstance();//调用无参构造器创建对象
2,利用class获得有参构造器,然后调用newInstance(参数...);
12.6 : 获取注解镜像:getDeclaredAnnotations(); 或者 getAnnotations();
注:获取方法上的注解就使用 method.getAnnotations();或者 method.getDeclaredAnnotations();
获取属性上的注解就使用 field.getAnnotations();...
十二.五:注解
@Target
表示注解能写在什么上面。作用于哪里。
METHOD 可用于方法上
TYPE 可用于类或者接口上
FIELD 可用于属性上
PARAMETER 可用于参数上
CONSTRUCTOR 可用于构造方法上
ANNOTATION_TYPE 可用于注解类型上(被 @interface修饰的类型)
LOCAL_VARIABLE 可用于局部变量上
PACKAGE 用于记录java文件的package信息
@Retention 保留
定义了该Annotation被保留的时间长短
1,仅出现在源代码中,而被编译器丢弃
2,被编译在class文件中
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
@Documented 文档API
annotation应该被作为被标注的程序成员的公共API
@Inherited 被继承的
@Inherited阐述了某个被标注的类型是被继承的
@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类
自定义注解:
public @interface A {}
给注解定义属性:
权限 参数 属性名 默认 值
public String value() default "";
注:权限只有public 和 默认的
参数支持的数据类型:
基本数据类型
String类型
Class类型,可以添加泛型
以及上面的数组类型
十三:可变参数
可以接受任意个同类型的数据。
13.1:语法: public void show(int... a);----> public void show(int[] a)
13.2:含义: 调用这个show方法的时候可以传入多个int数据
13.2.1: show(1); ---> show(new int[]{1});
13.2.2: show(1,2,3); ---> show(new int[]{1,2,3})
13.2.2: show(); ---> show(nnew int[0])
13.3:取值 可变参数有length属性.获取数组长度。-->取值同数组.
show(1,2,3,4);---->a[0],a[1],a[2],a[3]...
注意:可变参数一定是放在方法参数的最后一个。
eg: public void show(int a,String b,double... c){}
十四:forEach循环
14.1:语法 for(数据类型 变量 : 被遍历的数据){}
14.2:解释 : 使用 数据类型的变量来接收每次被遍历出来的数据
十五:枚举类型
JDK1.5增加了枚举类型,可以使用enum来定义,使用enum关键字 枚举和类一个级别。
eg:
public enum Gender{
MALE,FEMALE;
}
其中每一个枚举元素都是该枚举类型的一个实例
使用 Gender gender = Gender.MALE;
遍历 for(Gender s : Gender.values()) {}
1,实例:public enum Gender{
Man,WoMan;
}
表示:一个枚举类Gender,有两个对象Man和WoMan。
注: 其中每一个枚举元素都是该枚举类型的一个实例
2.获取枚举类型中的对象:
1, Gender gender = Gender.Man;
2, Gender gender = Gender.WoMan;
3, for(Gender g : Gender.values()){
syso(g);//Man,WoMan
}
3.Enum类和enum关键字的区别
1.使用enum关键字定义的枚举类型,实际上就相当于定义了一个类,此类继承了java.lang.Enum类
2.每一个枚举值都是一个枚举类型的实例,它们被预设为public static final
3. Enum类的只有一个受保护的构造方法 protectd Enum(String name,int ordinal)ordinal: 枚举元素的编号
4.实际上对于每一个枚举元素一旦声明之后,就表示自动调用此构造方法,所有的编号采用自动编号的方式进行(编号从0开始);
5.使用valueOf()方法,通过枚举类可以找到枚举中一个指定的对象
public enum Color{
RED,BLUE;
}
获得枚举类型对象的俩种方式:
第一种方式:
String s = "RED";
Color red = Color.valueOf(s);
第二种方式:
Color red = Color.RED;
第一种方式是通过一个字符串的值来获得对象的,只要我们改变字符串的值就随意改变要获得的对象.
第二种方式就是写死的代码,不管怎么执行都是拿到枚举类中 RED对象,永远都是这样。
4.枚举类型的属性和方法,枚举类型可以有属性和方法
规则如下:
属性和方法必须定义在元素列表声明之后
public enum Color{
RED,BLUE;
private String name;
public String getName(){
return this.name;
}
}
5. 枚举类型中定义构造方法
1.枚举的构造方法只能定义在元素列表之后
2.枚举类型的构造方法只能是private的,不写默认也是private
3.元素如果需要调用有参构造方法,则在元素后面加上"(参数)"
解释:Color类型只有三个固定对象,分别为RED GREEN BLUE,并且这个三个对象在创建的时候分别调用了有参的和无参的构造器
eg:
public enum Color {
RED("红色"),GREEN("绿色"),BLUE;
private String name;
public String getName(){
return this.name;
}
//一个参数构造器
Color(String name){
this.name = name;
}
//无参构造器
private Color(){
}
}
main:
//拿到Color中的三个固定对象的其中一个
Color c = Color.RED;
//拿到RED对象中的name属性的值
//这个值打印出来会是 "红色"
//因为是RED这个对象才创建的时候
//通过一个参数的构造器传给属性name的
//在枚举类型中声明元素列表其实就是
//在创建这个枚举类型的固定对象
String name = c.getName();
枚举隐式继承于Enum因此,无法再继承其他类
6. 枚举实现接口
枚举可以实现接口,有以下两种方式
1.与普通class类一样,在枚举类中实现接口一样
2.枚举中单独实现接口中的抽象方法或者各个枚举元素对象中分别实现这个接口中的抽象方法 public interface Sofa{
void sit();
}
第一种方式来实现接口
public enum Color implements Sofa{
RED("红色"),GREEN("绿色"),BLUE;
private String name;
public String getName(){
return this.name;
}
//一个参数构造器
Color(String name){
this.name = name;
}
//无参构造器
private Color(){
}
//枚举中单独实现,每一个枚举元素对象都可以调用到这个方法
public void sit(){
//....
}
}
第二种方式来实现接口
public enum Color implements Sofa{
//每一个枚举元素对象中单独实现这个接口中的抽象方法 将来每个枚举元素对象调用到的就是自己独立实现的这个sit方法
RED("红色"){
public void sit(){
//....
}
},
GREEN("绿色"){
public void sit(){
//....
}
},
BLUE{
public void sit(){
//....
}
};
private String name;
public String getName(){
return this.name;
}
//一个参数构造器
Color(String name){
this.name = name;
}
//无参构造器
private Color(){
}
} 6. 枚举中定义抽象方法
在一个枚举中可以定义多个抽象方法,但枚举中的每个元素必须分别实现这
些抽象方法
eg:
public enum Color {
RED{
public String getInfo() {
return "红色";
}
},
GREEN{
public String getInfo() {
return "绿色";
}
},
BLUE{
public String getInfo() {
return "蓝色";
}
};
public abstract String getInfo();
}