自己定义的Java中不存在的类型,并且取值范围比较少。
public enum Sex {
M("男"),F("女");
private final String value;
Sex(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
public class Test { public static void main(String[] args) { Sex sex = Sex.F; System.out.println(sex.getValue());
Sex[] sexes = Sex.values(); //将所有枚举值取出,组成一个值的集合
System.out.println(Arrays.toString(sexes));
System.out.println(Sex.valueOf("M"));
}
注解
注解是Java1.5之后带有的一种新的类型,主要用于标记类,属性,方法,参数等。
这种标记一定会被反射这种技术所使用。
如果没有反射,注解本身是不会发生任何作用。
public @interface A {
public static final int i = 1;
public abstract int f();
boolean g() default false;
double[] h() default {};
public abstract int value() default 3; // 此处的3表示这个value方法默认的返回值
// 如果方法的名字是value,那么这个名字是可以不用书写的
// public abstract void g(); // 注解中的方法不能返回void
// public abstract int f(int i); // 注解中的方法不能被重载 }
@A(f = 0)
public class Test {
}
元注解: 注解的注解
- @Target这个注解用来说明一个注解可以放在哪些内容上 如果没有加这个注解,则一个注解可以随意放在哪里都可以。 @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
- @Retention表示一个注解的生命周期(源代码<字节码<运行时) 它的含义是一个注解可以出现在哪个阶段中。 自定义注解一般都要求是运行时阶段存在的。为什么?反射这个机制只能在运行时出现
- @documented用来表示这个注解应该被收录在最后的Java文档中
反射: 在程序运行阶段,获取这个类中信息的能力。
获取哪些信息?属性,方法,构造器,注解。其余的暂时都获取不到。
Java中使用Class类来代表反射,所有类型都有自己的反射。获得反射一共有3种方式:
public class Test {
public static void main(@A(f = 3) String[] args) {
class User { //局部内部类
}
//第1种方式
Class c1 = User.class;
try {
//第2种方式
Class> c2 = Class.forName("com.example.A");
//>叫做通配泛型
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//第3种方式
Class extends User> c3 = new User().getClass();
// extends User>叫做受限泛型,表示尖括号里面必须是User或者是User的子类
}
}
使用反射操纵属性
public class User { private int i; public int j;
public User(int i, int j) {
this.i = i;
this.j = j;
}
@Override
public String toString() {
return "User{" +
"i=" + i +
", j=" + j +
'}';
}
}
public class Test {
public static void main(String[] args) {
Class c = User.class; //c表示的是User这个类的反射 //Field类表示的某个属性的反射
Field[] fields = c.getFields(); //getFields方法的含义是取得当这个类和所有父类中的可访问属性
Field[] declaredFields = c.getDeclaredFields(); //getDeclaredFields获得这个类中所有的属性
for (int i = 0; i < declaredFields.length; i++) {
System.out.println(declaredFields[i]);
}
}
}
属性的可能操作只有被赋值和读取其中的值,那么反射也能代替我们来做这两个操作。
属性的值要存在的前提是必须要有对象,反射也要如此。
import java.lang.reflect.Field;
public class Test { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Class c = User.class; //c表示的是User这个类的反射 User user1 = new User(1, 3); User user2 = new User(5, 6);
Field fieldJ = c.getField("j"); //getField用于获得当前类或其父类中某一个可以被访问的属性
System.out.println(fieldJ.get(user1));
System.out.println(fieldJ.get(user2)); //get方法用于取出某个对象中这个属性的值
fieldJ.set(user1, 100); //set方法用于设置某个属性的值
fieldJ.set(user2, 200);
System.out.println(user1);
System.out.println(user2);
}
}
import java.lang.reflect.Field;
public class Test { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Class c = User.class; //c表示的是User这个类的反射 User user1 = new User(1, 3); User user2 = new User(5, 6);
Field fieldI = c.getDeclaredField("i"); //getDeclaredField用于获得当前类中某一个属性
fieldI.setAccessible(true); //将一个属性设置为可访问的setAccessible
System.out.println(fieldI.get(user1));
System.out.println(fieldI.get(user2)); //get方法用于取出某个对象中这个属性的值
fieldI.set(user1, 100); //set方法用于设置某个属性的值
fieldI.set(user2, 200);
System.out.println(user1);
System.out.println(user2);
}
}
使用反射操纵方法
public class User {
public void f(){
System.out.println("不带参数的,返回值为void的方法f");
}
private void f(String s){
System.out.println("带String参数的,无返回值方法f");
}
private double f(int i, double d){
System.out.println("带int和double参数的,返回值为double的方法f");
return i + d;
}
}
public class Test {
public static void main(String[] args) throws Exception {
Class c = User.class; //c表示的是User这个类的反射
//Method和Filed类似,用于表示某一个方法的反射
Method[] methods = c.getMethods();//拿到当前类和父类中所有可访问的方法
Method[] methods1 = c.getDeclaredMethods(); //拿到当前类所有的方法
for (int i = 0; i < methods1.length; i++) {
System.out.println(methods1[i]);
}
}
}
针对于方法的操作实际上只有一个,那就是调用。
public class Test {
public static void main(String[] args) throws Exception {
Class c = User.class; //c表示的是User这个类的反射
Method publicMethodF = c.getMethod("f");
Method privateMethodF = c.getDeclaredMethod("f", int.class, double.class); //c.getDeclaredMethod("f", String.class);
User user = new User();
publicMethodF.invoke(user); //invoke专门用于反射中,调用一个方法
privateMethodF.setAccessible(true);
System.out.println(privateMethodF.invoke(user, 1, 3.14));
}
}
使用反射操纵构造器
public class User {
private int id;
private String name;
public User() {
System.out.println("无参数构造器");
}
private User(int i, String s) {
this.id = i;
this.name = s;
System.out.println("带参数构造器");
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + ''' +
'}';
}
}
public class Test {
public static void main(String[] args) throws Exception {
Class c = User.class; //c表示的是User这个类的反射
Constructor constructor1 = c.getConstructor();
User user1 = constructor1.newInstance();
System.out.println(user1);
Constructor constructor2 = c.getDeclaredConstructor(int.class, String.class);
constructor2.setAccessible(true);
User user2 = constructor2.newInstance(100, "tom");
System.out.println(user2);
}
}
使用反射操纵注解
public class User {
@Id(100)
private int id;
@Name("tom")
private String name;
}



