在正常的情况下,肯定是需要先知道一个类的完整的“包.类”之后再产生对象,如果说现在想反着来,通过一个给定的对象知道对象所属的“包.类”,那么就必须依靠Object类中的getClass()方法完成了。
public class APIDemo{
public static void main(String [] args){
java.util.Date date = new java.util.Date();
System.out.println(date.getClass().getName());
}
}
现在可以通过对象反向回去了,而getClass()方法的定义如下:
* Object 类定义方法:public final Class<?> getClass()
可以发现getClass()方法所返回的是一个Class类的实例化对
class Factory{
public static Fruit getFruit(String className){
Fruit instance = null;
try{
Class<?> cls = Class.forName(className);
instance = cls.newInstance();
}catch(Exception e){
e.printStackTrace();
}
return instance;
}
}
public class APIDemo{
Fruit f = Factory.getFruit(""org.lxh.demo.Apple);
f.eat();
}
象,而且还有泛型的定义,但是这种在反射上使用的泛型基本上没有任何的用处,都使用“?“表示。
取得Class类的实例化对象
对于Class类而言,其本身属于所有反射机制操作的源头,所以这个类的对象有三种实例化方式:
*方式一:利用Object类中的getClass()方法完成;
public class APIDemo{
public static void main(String [] args){
java.util.Date date = new java.util.Date();
System.out.println(date.getClass().getName());
}
}
*方式二:利用”类.class“取得Class类的实例对象;
public class APIDemo{
public static void main(String [] args) throws Exception{
Class<?> cls = java.util.Date.class;
System.out.println(cls.getName);
}
}
*方式三:利用Class类的一个static 方法完成:
方法:public static Class<?> forName(String className) throws ClassNotFoundException
|-此方法将传入一个完整的”包.类“名称,而后取得Class类的实例化对象;
public class APIDemo{
public static void main(String [] args){
Class<?> cls = Class.forName("java.util.Date");
System.out.println(cls.getName());
}
}
而这三种操作方法之中以forName()这种形式使用最多。
通过反射实例对象
当取得了一个实例化对象之后最大的好处是可以通过Class类的一个方法进行指定的对象实例化操作:
方法:public T newInstance() throws InstantinationException,IllegalAccessException
范例:定义一个Person类
Class Person{ public String toString(){ return "Person类的一个对象"; } }
正常情况下可以利用构造方法及关键字new进行对象的实例化操作:
public class APIDemo{ public static void main(String[] args) throws Exception{ Person per = new Person(); System.out.println(per); } }
如果说现在有了反射机制,则此种操作就可以改变了:
public class APIDemo{ public static void main(String [] args){ Class<?> cls = Class.forName("org.lxh.demo.Person"); Person per = (Person)cls.newInstance(); System.out.prinltn(per); } }
通过以上的代码可以发现,使用反射操作可以替代掉关键字new实例化对象的过程。
对于现在对象的两种实例化方式,最常用的还是关键字new,但是反射机制的操作有其固定的应用范畴。
范例:工厂设计模式
这种传统工厂设计模式有一个最大的问题在于:如果现在增加子类的话,一定要修改工厂类,那么如果说现在希望即使增加再多的子类,工厂类也可以不修改呢?那么就使用反射。
传统的工厂设计模式如下:
class Apple implements Fruit{ public void eat(){ System.out.println("***吃苹果"); } class Factory{ public static Fruit getFruit(String className){ if("apple".equals(className)){ return new Apple(); } return null; } } public class APIDemo{ public static void main(String[] args[]) throws Exception{ Fruit f = Factory.getFruit("apple"); f.eat(); } }
使用反射机制的工厂模式如下:
interface Fruit{ public void eat(); } class Apple implements Fruit{ System.out.println("***吃苹果"); } class Orange implements Fruit{ System.out.println("***吃橙子"); } class Factory{ public static Fruit getFruit(String className){ Fruit instance = null; try{ Class<?> cls = class.forName(className); instance = (Fruit)cls.newInstance(); }catch(Exception e){ e.printStackTrace(); } return instance; } } public class APIDemo{ public static void main(String [] args){ Fruit f = Factory.getFruit("org.lxh.demo.Orange"); f.eat(); } }
通过反射机制可以让程序开发更加的灵活,因为使用反射方式实例化对象的时候只需要传入完整的”包.类“的字符串名称即可。