※ 反射
提到反射可能会使我们联想到光学中的反射概念。
在Java中又是另外一个概念:
平时我们照镜子的时候,在镜子后面会有自己的影子,其实java中的反射也是类似的,一个类或者对象通过反射可以获得自身的对象,该对象是一个java.lang.Class 的对象(就像一个镜像文件)。
※ 一个对象或者类获得自身的Class对象的过程称为反射。
※ 反射一般用于,当只有一个类对象没有源代码的时候,为了获取类中方法和属性,构造器等。
※ Class类型 java.lang.Class类
1)Class是对java中所有类型的抽象。即一个Class类型对象可以表示出java中任意一种类型。
2)每种类型在加载到内存后,内存中都会生产一个与之对应的Class类型对象(有且只有一个),用来表示该类型。
3)每个类型都有且只有一个Class类型对象与之对应,通过这个Class类型对象就可以获得到该类型中的各种信息。
※ Class类是Java反射的入口.
反射机制通过在运行时探查字段和方法,从而可以帮助写出通用性很好的程序,这项能力对系统编程来说特别有用,但它并不适合于应用编程。而且,反射是脆弱的——编译不能帮助你发现编译错误,任何错误在运行时被发现并且都会导致异常。
1.表示基本类型
Class c = int.class;
System.out.println(c.isPrimitive());//true
System.out.println(c.getName());//int
注:其他基本类型的情况类似
2.表示类类型
注:s.getClass()方法返回的是变量s所指向对象的实现类型的Class对象。
Student s = new Student();
Class c1 = s.getClass();
Class c2 = Student.class;
System.out.println(c1 == c2);//true
//p指向的对象实际类型是Student
Person p = new Student();
Class c1 = p.getClass();//c1表示Student类型
Class c2 = Person.class;//c2表示Person类型
System.out.println(c1 == c2);//false
3.表示接口类型
Action a = new Student();
Class c1 = a.getClass();//c1表示Student类型
Class c2 = Action.class;//c2表示Action类型
System.out.println(c1 == c2);//false
System.out.println(c2.isInterface());//true
4.表示数组类型
int[] a = new int[4];
Class c1 = a.getClass();
Class c2 = int[].class;
System.out.println(c1 == c2);//true
System.out.println(c1.isArray());//true
Class c3 = c1.getComponentType();//c3表示该数组是使用什么类型声明出来的
System.out.println(c3.getName());//int
Student[] a = new Student[4];
Class c1 = a.getClass();
Class c2 = Student[].class;
System.out.println(c1 == c2);//true
System.out.println(c1.isArray());//true
Class c3 = c1.getComponentType();//c3表示该数组是使用什么类型声明出来的
System.out.println(c3.getName());//com.briup.test.Student
※ 获取镜像的方法
※ 获取基本数据类型的镜像
Class c=int.class
//false,Integer是包装类,不是基本数据类型
//Class c=Integer.class;
System.out.println(c);
※ 获取类(引用类型)的镜像
有三种方法可以获得自身的Class对象引用(对每一个被装载的类型(类或接口),虚拟机都会为它创建一个
java.lang.Class的实例);
1)虚拟机中没有该类的Class的实例对象,借助全包名.类名(全包名.接口名)。
try {
Class c2=Class.forName("com.briup.collection.map.ShopCart");
System.out.println(c2);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
2)知道类名时,直接类名.class获取镜像;
Class c1=ShopCart.class;
System.out.println(c1);
3)有类的实例时,基于对象获取镜像。
ShopCart cart=new ShopCart();
Class c=cart.getClass();
System.out.println(c);
注意:类和它所创建的所有对象通过反射获得的Class对象都是同一个。
※ 反射机制中的常见类的含义
java.lang包下:
Class 类 对java中所有类型抽象而得来的
package类 对java中所有包抽象而得来的
java.lang.reflect包下:
Modifier 类 对java中所有修饰符抽象而得来的
Field 类 对java中所有属性抽象而得来的
Method 类 对java中所有方法抽象而得来的
Constructor 类 对java中所有构造器抽象而得来的
Array 类 提供了对数组对象的动态访问
※ 反射的作用
反射可以让我们利用这个Class对象来获取和修改私有的变量和方法,不通过共有的方法去获得(原来我们例子都是通过一个public的方法来设置和获取私有的变量),可以破坏数据的封装性。
常用到反射方式:
1) 可以创建对象
2) 可以访问对象中的属性
3) 可以访问对象中的方法。
4) 可以访问对象中的构造器。
反射机制通过在运行时探查字段和方法,从而可以帮助写出通用性很好的程序,这项能力对系统编程来说特别有用,但它并不适合于应用编程。而且,反射是脆弱的——编译不能帮助你发现编译错误,任何错误在运行时被发现并且都会导致异常。
※ java.lang.Class类(API)
我们通过Class类,实现了反射的作用:例如:得到类的镜像名字,调用镜像类中属性,方法,构造器德等。
※ Class类中方法:
※ 关于类镜像的一些方法的验证:
package com.briup.reflect;
import com.briup.collection.map.Cart;
public class FirstReflect {
public void test(){
//获取基本数据类型的镜像
Class c=int.class;
System.out.println(c);
//获取镜像的名字
System.out.println(c.getName());
//判断某个镜像是不是基本数据类型
System.out.println(c.isPrimitive());
}
public void test1(){
//同一类型不管构建多少对象,模版都是一个
int [] n=new int[10];
int [] n1=new int[30];
boolean[] b=new boolean[10];
Class bc=b.getClass();
Class c=n.getClass();
Class c1=int[].class;
Class c2=n1.getClass();
// System.out.println(c1.getName());
// System.out.println(c2.getName());
// System.out.println(bc.getName());
//判断某一个镜像是不是一个数组的镜像
System.out.println(c1.isArray());
}
public void test2(){
//父类指向子类,获取的镜像是子类的,
Parent p=new Children();
Class c=Parent.class;
Class c1=p.getClass();
System.out.println(c);
//判断c1是不是c镜像的子类(子实现)
System.out.println(c.isAssignableFrom(c1));
}
public void test3(){
A ch=new Children();
Class c=ch.getClass();
Class c1=A.class;
// A b=new A(){};
// System.out.println(c1==b.getClass());
// System.out.println(c1);
//判断镜像是不是接口类型
System.out.println(c1.isInterface());
//判断c是不是c1的子实现
System.out.println(c1.isAssignableFrom(c));
Cart[] n=new Cart[10];
Class c2=n.getClass();
//获取数组镜像的类型
System.out.println(c2.getComponentType());
}
public void test4(){
//如果是基本数据类型,镜像的获取
Class c=int.class;
//如果是引用类型 镜像的获取3种
//构建对象的方法获取 getClass()
Cart cart=new Cart();
Class c1=cart.getClass();
//通过类名.class 接口.class 数组类型[].class
Class c2=Cart.class;
Class c3=A.class;
Class c4=Cart[].class;
//通过包名+类名(接口的名字获取镜像)
try {
Class c5=Class.forName("com.briup.collection.map.Cart");
System.out.println(c5);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
FirstReflect f=new FirstReflect();
f.test4();
}
}