反射与类操作

利用工厂类来进行设计。关于传统的工厂类。开发中用不到这种工厂类。传统工厂的工厂设计模式用不了。因为在实际使用的时候,如果增加新的类,就需要不停的修改Factory的类名称,非常麻烦。

interface IFruit {
 public void eat();
}class Apple implements IFruit {
 @Override
 public void eat() {
  System.out.println("[apple]吃苹果");
 }
}
class Orange implements IFruit {
 @Override
 public void eat() {
  System.out.println("[Orange]吃橘子");
 }
}
class Cherry implements IFruit {
 @Override
 public void eat() {
  System.out.println("[Cherry]吃樱桃");
 }
}
class Factory {
 private Factory() {}
 public static IFruit getInstace(String className) {
  IFruit fruit=null;
  try {
   fruit=(IFruit)Class.forName(className).newInstance();
  } catch (Exception e) {
   e.printStackTrace();// TODO: handle exception
  }
  return fruit;
 }
}public class TestDemo {
 public static void main(String[] args) throws Exception {
 IFruit fruit =Factory.getInstace("Cherry");
 fruit.eat();
 }
}

传入不同的类的时候,同一个功能可以保证不变。通过反射类改进工厂设计模式,其最大的特征在于动态进行子类的扩充操作。关键字new 会造成耦合问题。

然而,所有的工厂子类都是相似的相同功能,所以采用泛型来处理。使用泛型的话,工厂类就不必每次改变,从而为多种接口服务。

interface IFruit {
 public void eat();
}
interface IMessage {
 public void print();
}
class MessageImpl implements IMessage{
 @Override
 public void print() {
  System.out.println("hello world");// TODO Auto-generated method stub
 }
}
class Grapes implements IFruit{
 @Override
 public void eat() {
  System.out.println("吃到葡萄了");// TODO Auto-generated method stub
 }
}
class Apple implements IFruit {
 @Override
 public void eat() {
  System.out.println("[Apple]吃苹果");
 }
}
class Factory {
 private Factory() {}
 @SuppressWarnings("deprecation")
 public static <T> T  getInstace(String className) {
  T obj=null;
//  IFruit fruit=null;
  try {
   obj=(T)Class.forName(className).newInstance();
  } catch (Exception e) {
   e.printStackTrace();// TODO: handle exception
  }
  return obj;
 }
}public class TestDemo {
 public static void main(String[] args) throws Exception {
 IFruit fruit =Factory.getInstace("Apple");
 fruit.eat();
 IFruit grapes=Factory.getInstace("Grapes");
 grapes.eat();
 IMessage msg=Factory.getInstace("MessageImpl");
 msg.print();
 }
}

从而可以高效的利用工厂类,利用泛型来处理。

类中可以存在多种构造方法,使用Class类的方法取得指定参数类型的构造方法。Constructor()取得类中所有构造。 getConstructors()例子:取得类中所有构造方法的信息

import java.lang.reflect.Constructor;
class Person{
 public Person() {}
 public Person(String name) {}
 public Person(String name,int age) {}
}
public class TestDemo{
 public static void main(String[] args) throws Exception{
  Class<?> cls =Person.class;
  Constructor<?> conts[]=cls.getConstructors();
  for(int x=0;x<conts.length;x++) {
   System.out.println(conts[x]);
  }
 }
}

以上的操作利用的是Constructors 的toString()方法,这个信息输出的是完整的,而如果用getName ()方法。则会麻烦,因为只能得到名字而得不到参数和方法的私有情况。

构造方法的定义基本上不会用的到,但是类中的不可避免的会有大量的重复的代码。1、取得全部方法 getMethords()2、取得部分方法 getMethord()以上两个方法返回的类型是java .lang.reflact.Methord 类的对象
有一个最重要的方法时invoke(Object obj,Object……args) 方法在此类中提供有一个调用的方法支持范例:取得类中的全部方法。
getMethod 可以取得全部的方法。

import java.lang.reflect.Method;
class Person{
 private String name;
 public void setName(String name) {
  this.name = name;
 }
 public String getName() {
  return name;
 }  
}
public class TestDemo{
 public static void main(String[] args) throws Exception{
  Class<?> cls =Person.class;
  Method[]  met=cls.getMethods();
  for(int x=0;x<met.length;x++) {
   System.out.println(met[x]);
  }
 }
}

有了反射之后,即使没有明确的Person类对象,(但仍然需要实例化)Object,可以通过反射来调用setter和getter(有明确开发要求)。这种类型,不再局限于某一具体类型的对象,而是可以通过Object采用所有方法的调用。

import java.lang.reflect.Method;
class Person{
 private String name;
 public void setName(String name) {
  this.name = name;
 }
 public String getName() {
  return name;
 }  
}
public class TestDemo{
 public static void main(String[] args) throws Exception{
  Class<?> cls =Person.class;
  Method[]  met=cls.getMethods();
  for(int x=0;x<met.length;x++) {
   System.out.println(met[x]);
  }
 }
}
有了反射之后,即使没有明确的Person类对象,(但仍然需要实例化)Object,可以通过反射来调用setter和getter(有明确开发要求)。这种类型,不再局限于某一具体类型的对象,而是可以通过Object采用所有方法的调用。
import java.lang.reflect.Method;class Person{
 private String name;
 public void setName(String name) {
  this.name = name;
 }
 public String getName() {
  return name;
 }  
}
public class TestDemo{
 public static void main(String[] args) throws Exception{
  String attribute="name";
  String value="mldn";
  Class<?> cls =Person.class;
  @SuppressWarnings("deprecation")
  Object obj=cls.newInstance();//调用类中的普通方法要有实例化对象。
  //setName是方法名称,但是这个方法时根据给定的属性信息拼凑得来的。该方法需要一个String形的参数
  Method setMethod=cls.getMethod("set"+initcap(attribute), String.class);
  //需要通过Method类对象来调用指定对象,调用方法必须要有实例化对象,同时要传入一个参数
  setMethod.invoke(obj, value);//相当于Person对象.setName(value)
  Method getMethod=cls.getMethod("get"+initcap(attribute));
  Object ret=getMethod.invoke(obj);//相当于Person对象.getNeme()
  System.out.println(ret);
 }
 /**
  * 创建一个方法,使得方法名称的首字母大写
  */
 public static String initcap(String str) {
  return str.substring(0, 1).toUpperCase()+str.substring(1);
 }
 
}

调用类成员在此之前,已经成功实现了 类的构造调用、方法调用,目前介绍成员调用。前提:类中的对象要在实例化后,才能进行空间的分配。所以此时如果要调用类的属性,必须保证有实例化对象newInstance()方法来完成实例化。例子:

import java.lang.reflect.Field;
class Person{
 public String name;
}
class Student extends Person{//利用继承
 private String school;
}
public class TestDemo{
 public static void main(String[] args) throws Exception{
  Class<?> cls =Class.forName("Student");
  {
   Field fields[]=cls.getFields();//取得父类属性
   for(int x=0;x<fields.length;x++) {
    System.out.println(fields[x]);
   }
  }
  System.out.println("__________________");
  {
   Field fields[]=cls.getDeclaredFields();//取得本类属性
   for(int x=0;x<fields.length;x++) {
    System.out.println(fields[x]);
   }
  }
 }
 
}

class 类中有提供取得属性的方法:
一、取得父类属性
1、取得类中全部属性、public Field[] getFields() throws SecurityException
2、取得类中的指定名称的属性
二、取得本类属性
1、public Field[] getDeclaredFields() throwsSecurityException
2、public Field[] getDeclaredFields(String name) throws NoSuchFeldException,SecurityException
现实开发中,属性都会进行封装处理,自然没有必要关注父类的属性,所以一本类属性为主,也就是用getDeclaredFields()
设置属性内容:set(Object obj)取得属性内容:get(Object obj)
例子:【通过反射操作属性】




import java.lang.reflect.Field;
class Person{
 private String name;
}public class TestDemo{
 public static void main(String[] args) throws Exception{
  Class<?> cls =Class.forName("Person");
  Object obj=cls.newInstance();
  Field nameField=cls.getDeclaredField("name");
  nameField.setAccessible(true);//临时取消了封装的属性
  nameField.set(obj,"张三");//此处等价于 对象.name=“张三”;
  System.out.println(nameField.get(obj));//取得属性
 }
}

观察java的反射集成结构,class 可以操作Constructor,Method ,Field,这三个都是AccessableObject的子类,constructor 和Method是executor 的子类。
setAccessible,动态设置封装。以临时取消封装,也就是说,可以在方法内进行封装取消。
但是还是seter和geter方式对用户来说最合适。给用户的操作空间更大。

import java.lang.reflect.Field;
class Person{
 private String name;
}public class TestDemo{
 public static void main(String[] args) throws Exception{
  Class<?> cls =Class.forName("Person");
  Object obj=cls.newInstance();
  Field nameField=cls.getDeclaredField("name");

  System.out.println(nameField.getType().getName());//包.类
  System.out.println(nameField.getType().getSimpleName());//类
 //即使前面有私有化的成员内容,同样可以利用getType()方法来获取到属性。
 }
}

getType()方法的使用,将Filed取得属性与Method类中的invoke()结合在一起,就可以编写非常灵活的程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值