类型一:利用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();
}
}
这样实现的工厂设计模式最大的好处在于:即使在程序开发的时候类不存在,也不会出现语法错误,而且工厂类可以在扩充子类的时候保持统一风格.
但是这个操作有一个最大的缺点:智能够调用无参构造.