Java反射机制

本文深入讲解Java反射机制的基础概念及其实现方式,并演示如何利用反射创建对象实例,同时探讨其在设计模式中的应用,特别是解耦合的设计理念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、认识反射:
Object类里面提供有一个方法,用于取得Class对象:public final Class<?>getClass();
范例:
public class TestDemo{
   public static main(String []args) throws Exception{
      Date date = new Date();//产生对象
 System.out.println(date.getClass());
   }
}
运行结果为:class java.util.Date;
发现调用getClass()方法后的输出就输出了类的完整名称,等于找到了对象的出处。




Class类对象实例化:
java.lang.Class是一个类,这个类是反射操作的源头,即:所有的反射都要从此类开始进行,此类有三种实例化方式:
   1.调用Object类中的getClass()方法
   eg:
   public static void main(String []args)throws Exception{
      Date date = new Date();//产生对象
      Class<?> cls = date.getClass();
 System.out.println(cls);
   }
   2.第二种:使用“类class取得”
   eg:
   public static void main(String []args) throws Exception{
      Class<?> cls = Date.class;
 System.out.println(cls);
   }
   输出结果与上面相同
  之前是产生了类的实例化对象之后取得的Class类对象,但是此时并没有实例化对象的产生。
   3.第三种:调用Class类提供的一个方法:
      实例化Class对象:public static Class<?>forName(String className);
 eg:
 public static void main(String[] args) throws Exception{
    Class<?> cls = Class.forName("java.util.Date");
System.out.println(cls);
 }
   此时可以不使用import语句导入一个明确的类,而类名称是采用字符串的形式进行描述的。
   
二、反射实例化对象:
当拿到一个类时候,肯定要直接使用关键字new进行对象的实例化操作,这属于习惯性动作,但是如果有了Class类对象,就可以利用发射实现对象实例化操作。
   实例化对象方法:public T newInstance()throws InstantiationException,Illegal
 范例:利用反射实例化对象
   package cn.mldn.demo;
   class Book{
      public Book(){
    System.out.println("*****Book类的无参构造方法*****");
 }
 @Override
 public String toString(){
     return "这是一本书";
 }
   }
   public class TestDemo{
      public static void main(String[] args) throws Exception{
    Class<?> cls = Class.forName("cn.mldn.demo.Book");//相当于找到Book类
Object obj = cls.newInstance();//相当于使用new调用无餐构造实例化
Book book = (Book) obj;//向下转型
System.out.println(book);
 }
   }
   有了反射之后,进行对象实例化的操作不再只是单独的依靠关键字new完成了,反射也可以完成,但是这并不表示new被完全取代了。
   在任何的开发之中,new是造成耦合的最大元凶,一切的耦合都起源于new。
范例:观察工厂设计模式
interface Fruit{
   public void eat();

class Apple implements Fruit{
   @Override
   public void eat(){
      System.out.println("吃苹果!");
   }
}
class Factory{
   public static Fruit getInstance(String className){
      if("apple".equals(className)){
    return new Apple();
 }
 return null;
   }
}   
public class TestFactory{
   public static void main(String []args){
     Fruit f = Factory.getInstance("apple");
f.eat();
   }
}   
如果此时增加了Fruit接口子类,就表示程序要修改工厂类。
 interface Fruit{
   public void eat();

class Apple implements Fruit{
   @Override
   public void eat(){
      System.out.println("吃苹果!");
   }
}
class Banana implements Fruit{
   @Override
   public void eat(){
      System.out.println("吃香蕉!");
   }
}
class Factory{
   public static Fruit getInstance(String className){
      if("apple".equals(className)){
    return new Apple();
 }else if("banana".equals(className)){
    return new Banana();
 }
 return null;
   }
}   
public class TestFactory{
   public static void main(String []args){
     Fruit f = Factory.getInstance("apple");
f.eat();
   }
}  
每增加一个类就要去修改工厂类,那么如果我们随时都可能增加子类怎么办?  
因为工厂类中的对象都是通过关键字new直接实例化的,而new就成了所有问题的关键点。要想解决这一问题,就只能依靠反射来完成。
  interface Fruit{
   public void eat();

class Apple implements Fruit{
   @Override
   public void eat(){
      System.out.println("吃苹果!");
   }
}
class Banana implements Fruit{
   @Override
   public void eat(){
      System.out.println("吃香蕉!");
   }
}
class Factory{
   public static Fruit getInstance(String className){
      Fruit f = null;
 try{
   f = (Fruit)Class.forName(className).newInstance();
 }catch(Exception e){
   return f;
 }
   }
}   
public class TestFactory{
   public static void main(String []args){
     Fruit f = Factory.getInstance("cn.mldn.test.Apple");
f.eat();
   }
}  
 此时的程序就真正完成了解耦合的目的,而且可扩展性非常的强。  
      
注意:反射的所有泛型都是"?"
   
   
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值