package com.alpha;
import java.util.Date; // 先有类
public class MainClass{
public static void main(String[] args) throws Exception {
Date date = new Date(); // 产生对象
System.out.println(date);
}
}
所谓反射就是可以利用对象找到对象的出处,在Object类里面提供有一个方法:
取得Class对象:public final Class<?> getClass()
范例: 观察反射
package com.alpha;
import java.util.Date; // 先有类
public class MainClass{
public static void main(String[] args) throws Exception {
Date date = new Date(); // 产生对象
System.out.println(date.getClass());
}
}
实例化对象方法:public T newInstance() throws InstantiationException, IllegalAccessException
范例: 利用反射实例化对象
package com.alpha;
class Book {
public Book() {
System.out.println("Book without parameters of the construction method.");
}
@Override
public String toString() {
return "This is a book.";
}
}
public class MainClass{
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.alpha.Book");
Object obj = cls.newInstance(); // 相当于使用new调用无参构造实例化
System.out.println(obj);
}
}
package com.alpha.factory;
interface Fruit {
public void eat();
}
class Apple implements Fruit {
@Override
public void eat() {
System.out.println("eat apple");
}
}
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接口子类,那么就表示程序要修改工厂类。
class Orange implements Fruit {
@Override
public void eat() {
System.out.println("eat orange");
}
}
class Factory {
public static Fruit getInstance(String className) {
if ("apple".equals(className)) {
return new Apple();
} else if ("orange".endsWith(className)) {
return new Orange();
}
return null;
}
}
package com.alpha.factory;
interface Fruit {
public void eat();
}
class Apple implements Fruit {
@Override
public void eat() {
System.out.println("eat apple");
}
}
class Orange implements Fruit {
@Override
public void eat() {
System.out.println("eat orange");
}
}
class Factory {
public static Fruit getInstance(String className) {
Fruit f = null;
try {
f = (Fruit) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
public class TestFactory {
public static void main(String[] args) {
Fruit f = Factory.getInstance("com.alpha.factory.Apple");
f.eat();
}
}
此时的程序就真正完成了解耦合的作用,而且增强了程序的可拓展性。
使用反射调用构造
在之前所编写的代码实际上都默认使用了类中的无参构造方法,但是并不是所有的类都提供有无参构造。
范例: 观察程序的问题
package com.alpha.entity;
public class Book {
private String title;
private double price;
public Book(String title, double price) {
this.title = title;
this.price = price;
}
@Override
public String toString() {
return "Book [title=" + title + ", price=" + price + "]";
}
}
由于此时Book类没有提供无参构造方法,所以以下的代码是错误的。
package com.alpha;
public class MainClass{
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.alpha.entity.Book");
Object obj = cls.newInstance(); // 相当于使用new调用无参构造实例化
System.out.println(obj);
}
}
Exception in thread "main" java.lang.InstantiationException: com.alpha.entity.Book
at java.lang.Class.newInstance(Unknown Source)
at com.alpha.MainClass.main(MainClass.java:6)
Caused by: java.lang.NoSuchMethodException: com.alpha.entity.Book.<init>()
at java.lang.Class.getConstructor0(Unknown Source)
... 2 more