学习目标:掌握实例化类的另外一种技术——反射技术。
在Java程序设计中,实例化类的方式一般是使用new运算符,new运算符会创建类的一个实例,类的实例也称为实例对象或对象,并返回创建的实例对象的引用。
类的实例化
案例1:分别建立Book类和BookManager类。Book类有bookName和bookAuthor属性;在BookManager类定义了loadBookWithNew()方法,该方法使用new运算符加载Book类,并创建Book类的实例对象,BookManager类的main()方法调用loadBookWithNew()方法实例化Book类。
新建项目PUnit13,在PUnit13项目新建reflex包,在reflex包下新建Book类。代码如下:
package reflex;
public class Book {
// 图书名称
private String bookName;
// 图书作者
private String bookAuthor;
/**
* 无参构造函数
*/
public Book() {
super();
}
public Book(String bookName, String bookAuthor) {
super();
this.bookName = bookName;
this.bookAuthor = bookAuthor;
}
/**
*
* 重写父类的toString() 以字符串方式返回类信息
*/
@Override
public String toString() {
return "Book [bookName=" + bookName + ", bookAuthor=" + bookAuthor + "]";
}
/**
* 返回Book类的bookName属性
*/
public String getBookName() {
return bookName;
}
/**
* @param 设置Book类的bookName属性
*/
public void setBookName(String bookName) {
this.bookName = bookName;
}
/**
* 返回Book类的bookAuthor属性
*/
public String getBookAuthor() {
return bookAuthor;
}
/**
* @param 设置Book类的bookAuthor属性
*/
public void setBookAuthor(String bookAuthor) {
this.bookAuthor = bookAuthor;
}
}
Book类重写了父类的toString()方法,以字符串方式返回Book类的成员变量信息。
在reflex包下新建BookManager类。代码如下:
package reflex;
public class BookManager {
public static void main(String[] args) {
// 调用loadBookWithNew()方法
loadBookWithNew();
}
/**
* 使用new运算符实例化Book类
*/
public static void loadBookWithNew()
{
Book tempBook = new Book();
tempBook.setBookName("java技术深入理解");
tempBook.setBookAuthor("编程训练营");
//以字符串方式输出类信息
System.out.println(tempBook.toString());
}
}
当程序中需要实例化类时,常用方法是使用new运算符,new运算符是如何把类实例化为对象的呢?
Java类经过编译后会生成class文件,也就是字节码文件。如果该类没有加载到内存,new运算符会调用类加载器(ClassLoader)来加载类到内存,类加载器根据new传入的类名称在运行的Java程序路径中查找要加载的类,如果找到与该类名称相对应的字节码文件,类加载器会把类的字节码文件读入内存,并创建一个java.lang.Class对象(Class对象是该类所有实例化对象在内存中的代理)。如果该类有父类,类加载器也会把父类加载到内存中。类加载器完成类的加载任务后,new会完成类加载的后续工作,最后返回实例化对象的引用给对象变量。
对象变量会调用类提供的方法执行类提供的功能,获取或设置类的属性。例如:在前面案例代码BookManager类的loadBookWithNew方法中,实例化的类对象tempBook会调用Book类提供的set方法来设置Book类的属性,同时调用Book类的toString()方法以字符串方式获取类的信息,类的这些属性和方法在代码编译之前是必须要确定的。如果用new加载类后,类缺少这些方法和属性,编译器就会报错。因此new加载类属于静态加载,要接受编译器的检查。
反射技术
另外一种实例化对象的方式,就需要用到Java语言的反射机制。在本课内容中,先不具体介绍反射机制的工作原理及构成。先用反射技术来实例化对象,对反射有感性认识后,再具体介绍反射的工作原理及构成。
案例2:建立BookManager1类,该类定义loadBookWithRelflect()方法,该方法用反射来实例化类,可以实现和案例1方法loadBookWithNew()方法同样的效果。
在reflex包下新建BookManager1类。代码如下:
package reflex;
public class BookManager1 {
public static void main(String[] args) {
// 调用loadBookWithRelflect()方法
loadBookWithRelflect();
}
public static void loadBookWithRelflect() {
try {
Class<?> classBook = Class.forName("reflex.Book");
Object objectBook = classBook.newInstance();
Book tempBook = (Book) objectBook;
tempBook.setBookName("java核心技术课程");
tempBook.setBookAuthor("编程训练营");
System.out.println(tempBook.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
ookManager1类的loadBookWithRelflect()方法,利用Class.forName()方法加载Book类并返回Class对象(Class类会在下一课学习),然后调用Class对象的newInstance()方法实例化Book类,因为newInstance()方法返回Object类型,因此需要将返回的类型显示转换为Book类型。
从上面的执行结果可以看出,实例化类对象时,除了使用new运算符外,还可以使用Class对象的forName和newInstance()方法来实例化类对象。