1.获取Class对象 在Class类中,只定义了个私有的构造方法,这意味着,无法通过new Class()方式创建一个Class对象。 /*
* Constructor. Only the Java Virtual Machine creates Class
* objects.
*/
private Class() {} 虽然无法直接使用new Class()方式创建对象,但是Class类中提供了forName()方法,通过它仍然可以获得Class对象。 public static Class<?> forName(String className)
throws ClassNotFoundException {
return forName0(className, true, ClassLoader.getCallerClassLoader());
}
public static Class<?> forName(String name, boolean initialize,
ClassLoader loader)
throws ClassNotFoundException 除了使用forName()方法获得Class对象外,上面说过了Object是所有类的父类,而Object中有getClass()方法,所以通过"类名.getClass()"也可以获得Class对象,也可以通过“类名.class" package test;
public class A1 {
}
/**
* 获取Class对象
*/
public class A2 {
public static void main(String[] args){
Class<?> c1=null;
Class<?> c2=null;
Class<?> c3=null;
try {
c1=Class.forName("test.A1");//通过forName()获取
c2=A1.class;//通过"类名.class"获取
A1 a1=new A1();
c3=a1.getClass();//通过"对象.getClass()"获取
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("类路径:"+c1.getName());
System.out.println("类路径:"+c2.getName());
System.out.println("类路径:"+c3.getName());
}
} 运行结果 类路径:test.A1 类路径:test.A1 类路径:test.A1 通过运行结果可知,3种实例化Class对象的方式是一样的,但是使用forName()是较为常用的一种(当然,如果使用Hibernate或spring等框架时,经常使用"类.class“方式传送一个JavaBean实体)。 下面先看过设计上比较丑陋的例子。 package test;
/**
* 水果类接口
* 所有水果必须实现此接口
*
*/
public interface Fruit {
public void say();
}
package test;
/**
* 苹果类,实现接口Fruit
*
*/
public class Apple implements Fruit {
@Override
public void say() {
System.out.println("hello,I'm apple!");
}
}
/**
* 香蕉类,实现接口Fruit
*
*/
public class Banana implements Fruit {
@Override
public void say() {
System.out.println("hello,I'm banana!");
}
}
package test;
/**
* 水果工具类
*
*/
public class FruitUtil {
public static Fruit createFruit(String fruitName){
if("apple".equalsIgnoreCase(fruitName)) return (Fruit)new Apple();
if("banana".equalsIgnoreCase(fruitName)) return (Fruit)new Banana();
return null;
}
}
package test;
/**
* 测试类
*
*/
public class Test {
public static void main(String[] args){
Fruit f=FruitUtil.createFruit("apple");
if(f!=null) {
f.say();
}else{
System.out.println("没有水果!");
}
}
}
运行结果 hello,I'm apple! 代码没错,运行结果也没错,我之所以说它丑陋,是从代码扩展性方面考虑。比如,如果我要再添加一种水果呢?那么就必须修改FruitUtil.createFruit()方法中的代码了,增加if判断。那如果我要新曾几十种水果呢?那是不是要写几十个if判断。。。。。作为一个接触JAVA两年的菜鸟的我,都觉得代码设计不友好了,更别说修改原有代码对系统的危害了。那有没有一种方法,当新增水果时,不需要对原有代码做任何修改呢?有,这时,Class.forName()一声大哄,粉墨登场了。 package test;
/**
* 水果类接口
* 所有水果必须实现此接口
*
*/
public interface Fruit {
public void say();
}
package test;
/**
* 苹果类,实现接口Fruit
*
*/
public class Apple implements Fruit {
@Override
public void say() {
System.out.println("hello,I'm apple!");
}
}
package test;
/**
* 香蕉类,实现接口Fruit
*
*/
public class Banana implements Fruit {
@Override
public void say() {
System.out.println("hello,I'm banana!");
}
}
package test;
/**
* 水果工具类
*
*/
public class FruitUtil {
public static Fruit createFruit(String classPath)throws Exception{
Fruit fruit=null;
try {
fruit=(Fruit)Class.forName(classPath).newInstance();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("创建水果失败!");
}
return fruit;
}
}
package test;
import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
/**
* 测试类
*
*/
public class Test {
private final static String FRUIT_CONF_PATH=System.getProperty("user.dir");
public static void main(String[] args){
Properties p=new Properties();
try {
//在eclipse下建立普通JAVA项目,src写的内容放在bin下了
FileInputStream in=new FileInputStream(new File(FRUIT_CONF_PATH+File.separator+"bin"+File.separator+"fruit.properties"));
p.load(in);
String fruitClassPath=p.getProperty("apple");
p.clear();
in.close();
Fruit f=FruitUtil.createFruit(fruitClassPath);
f.say();
} catch (Exception e) {
e.printStackTrace();
System.out.println("获取水果实例失败!");
}
}
} fruit.properties配置文件 apple=test.Apple
banana=test.Banana 运行结果 hello,I'm apple! 这样改写后,以后有新增水果时,只要编写新增水果类,并再配置文件中配置新水果的类路径就OK了,原有的代码不需要修改。 这样的设计就具有很好的扩展性。 |
发表评论 取消回复