类型一:利用Object类之中的getClass()方法
方法:public final Class<?> getClass(),所有实例化的类都可以调用此方法.
import java.util.Date; public class Dome1 { public static void main(String[] args) { Date date=new Date(); Class<?> cls=date.getClass(); System.out.println(cls); } }
在任何的开发中,这种调用getClass()的方法很少使用,如果想要使用它也必须结合特定的环境.
类型二:使用"类.class"取得 的形式取得反射的实例化对象.
public class Dome1 { public static void main(String[] args) { Class<?> cls=java.util.Date.class; System.out.println(cls); } }
这样的操作形式只有在框架技术上才会使用到.
以上的两种形式都有一个本质的相同点:类必须首先存在,而后才可以进行反射的调用.
类型二:利用Class类提供的方法实例化对象.
方法:public static Class<?> forName(String className) throws ClassNotFoundException.
public class Dome1 { public static void main(String[] args) throws ClassNotFoundException { Class<?> cls=Class.forName("java.util.Date"); System.out.println(cls); } }
利用forName()方法进行Class类对象取得,其最大的特征是可以在类不存在的时候保持程序编译的正确性.
利用反射实例化对象
如果说要想实例化一个类的对象,那么最直观的做法一定是使用关键字newwancheng,但是从一个优秀的框架来讲,是不能够使用new(它应该是出现最少的关键字 ),主要是因为所有的开发不能够与具体的类型耦合在一起.
范例:传统对象实例化操作
public class Dome2 { @Override public String toString() { // TODO 自动生成的方法存根 return "这是一个部门的对象"; } }
public class Dome2_1 { public static void main(String[] args) { Dome2 dome2=new Dome2(); System.out.println(dome2); } }
功能完全相同的操作可以利用反射机制来进行处理,在Class类里面提供有一个实例化对象的方法
实例化对象:public T newInstance() throws
InstantiationException,IllegalAccessException
范例:利用反射实例化:
public class Dome2_1 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class<?> cls=Class.forName("cn.zwb.dome1.Dome2"); Object obj=cls.newInstance(); System.out.println(obj); } }
public class Dome2 { public Dome2() { System.out.println("===Dome2===="); } @Override public String toString() { return "这是一个部门的对象"; } }
现在给出了两种方式进行对象1实例化操作,这两种方式有什么样的区别呢?
在面向对象的设计过程之中一直强调一个观点:避免耦合操作.
范例:
interface Fruit{ public void eat(); } class Apple implements Fruit{ @Override public void eat() { System.out.println("吃苹果"); } } class Factroy{ //工厂类 public static Fruit getInstance(String className){ if("apple".equals(className)){ return new Apple() ; } return null; } } public class TestFactoryDomeA { public static void main(String[] args) { Fruit f=Factroy.getInstance("apple");//客户端不关心对象从哪里来,只关心能不能取得对象 f.eat(); } }
在开发之中如果是由你自己定义的接口,要取得实例化对象,不能够直接采用关键字new利用结构向上转型为接口对象实力还,而是采用工厂设计模式取得,
以上的像是只是一个简单工厂形式,如果说现在要想进行子类的扩充,那么必然要去修改工厂类;如果采用最为直观的编码,那么最大的问题也就出现,只要增加子类就要去修改工厂类,在代码量小的情况下,这不是个问题.但是一旦代码量很大,那么就有可能顾不上编写工厂类.所以与手工的代码比起来,自动的方式会比较好一些,要想在Java程序避免耦合性的问题发生,就只有采用反射机制来进行处理.
范例:
interface Fruit{ public void eat(); } class Apple implements Fruit{ @Override public void eat() { System.out.println("吃苹果"); } } class Factroy{ //工厂类 public static Fruit getInstance(String className){ Fruit fruit=null; try { fruit=(Fruit)Class.forName(className).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } return fruit; } } public class TestFactoryDomeA { public static void main(String[] args) { Fruit f=Factroy.getInstance("cn.zwb.dome1.Apple"); f.eat(); } }
这样实现的工厂设计模式最大的好处在于:即使在程序开发的时候类不存在,也不会出现语法错误,而且工厂类可以在扩充子类的时候保持统一风格.
但是这个操作有一个最大的缺点:智能够调用无参构造.