反射机制(一)

类型一:利用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();
	}
}

这样实现的工厂设计模式最大的好处在于:即使在程序开发的时候类不存在,也不会出现语法错误,而且工厂类可以在扩充子类的时候保持统一风格.

    但是这个操作有一个最大的缺点:智能够调用无参构造.

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值