本博客同系列有:
Java之------类反射系列(二)
Java之------类反射系列(三)
什么是类反射
☆什么是反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
反射(Reflection)是Java程序开发语言的特征之一,它允许运行中的Java程序对自身进行检查, 也称自审,并能直接操作程序的内部属性。例如,使用它能获得Java类中各成员的名称并显示出来。
Java的这一能力在实际应用中应用得很多,在其它的程序语言中根本就不存在这一特性。例如,Pascal、C或者C++中就没有办法在程序中获得函数定义相关的信息。
JavaBean是类反射的实际应用之一,它能让一些工具可视化的操作软件组件。这些工具通过类反射动态的载入并取得Java组件(类)的属性。后面学习的各种框架,基本上都会有反射的使用。
反射引例:
HelloWorld引例:
package cn.hncu.hello; import java.lang.reflect.Method; public class ReflectionHelloWorld { /** * @param args */ public static void main(String[] args) { try { Class c=Class.forName("cn.hncu.introduce.Person");//必须写完整类名 // System.out.println(c); Method ms[] = c.getDeclaredMethods(); for (Method m:ms){ System.out.println(m); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }USB引例:
此例在导入类名的时候采用的是:新建一个.config文件,在该文件中写上需要导的类的全名,然后在要使用的时候采用IO读取里面的内容,里面一次只存放一个类名,其他需要用的可在前面加上“#”号做注释,如下为usb.config文件:
#name=cn.hncu.usb.impl.UsbOne #name=cn.hncu.usb.impl.UsbTwo name=cn.hncu.usb.impl.UsbMouseUSB接口:
package cn.hncu.usb.api; public interface USB { public void work(); }实现类(本来写了多个,但只是类名不同,其他都是类似的,于是只写一个示范了):
package cn.hncu.usb.impl; import cn.hncu.usb.api.USB; public class UsbOne implements USB { @Override public void work() { System.out.println("UsbOne............."); } }工厂类:
package cn.hncu.usb.factory; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Properties; import cn.hncu.usb.api.USB; public class UsbFactory { public static USB getUsb(){ USB usb=null; try { Properties p=new Properties(); FileInputStream fis=new FileInputStream(new File("usb.config"));<span style="font-family: Arial, Helvetica, sans-serif;">//这就是前面提到的导入usb.config里的类名</span> p.load(fis); String fileName=p.getProperty("name");//此"name"为usb.config中的key值,可得到相应的value Class c=Class.forName(fileName); usb=(USB) c.newInstance(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return usb; } }模拟客户端:
package cn.hncu.usb; import cn.hncu.usb.api.USB; import cn.hncu.usb.factory.UsbFactory; public class Client { /** * @param args */ public static void main(String[] args) { USB usb=UsbFactory.getUsb(); usb.work(); } }
运行结果:
通过对象的getClass方法进行获取。这种方式需要具体的类和该类的对象,以及调用getClass方法。
★ 方式二
任何数据类型(包括基本数据类型)都具备着一个静态的属性class,通过它可直接获取到该类型对应的Class对象。这种方式要使用具体的类,然后调用类中的静态属性class完成,无需调用方法,性能更好。
★ 方式三
通过Class.forName()方法获取。这种方式仅需使用类名,就可以获取该类的Class对象,更有利于扩展。
举例:
package cn.hncu.reflect; public class ReflectGetClass { /** * @param args * Three manners to get the object of Class */ public static void main(String[] args) { getClassObj1(); getClassObj2(); getClassObj3(); test(); } private static void test() { Person p=new Person(); Object obj=(Object)p; Class c=obj.getClass();//运行时多态,new谁调谁 System.out.println(c);//class cn.hncu.reflect.Person System.out.println(int.class);//int System.out.println(Integer.class);//class java.lang.Integer System.out.println(Integer.TYPE);//int } private static void getClassObj3() { //3用字符串(类名)---依赖于String类 try { Class c=Class.forName("cn.hncu.reflect.Person"); System.out.println(c); } catch (ClassNotFoundException e) { e.printStackTrace(); } } private static void getClassObj2() { //2通过类名----依赖于Person类 Class c=Person.class; System.out.println(c); } private static void getClassObj1() { //1通过对象 Person p1=new Person(); Class c1=p1.getClass(); Person p2=new Person(); Class c2=p2.getClass(); System.out.println(p1==p2);//不同的对象 System.out.println(c1==c2);//同一个类模板,所有对象是共享同一个类模板的 } }