Class 类的使用
在 Java 面向对象的世界里,万事万物皆对象!
- 但是注意 Java 语言中,静态成员、普通数据类型都不是对象(封装类弥补了普通数据类型的不足)
- 我们所编写的每一个类都是对象,类是 java.lang.Class 类的实例对象。 There is a class named Class 即这里有一个名称为 Class 的类,我们所写的每一个对象所属的类都是它的实例
Class 类的实例对象如何获取?
有以下代码中的三种方式:
package com.fy.reflect;
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
// 类 A 的实例对象如何表示
A a = new A();
/* 类 A 也是 Class 类一个实例对象,因为任何一个类都是 Class 类的实例对象,
* 官网称之为类类型,有如下三种表示方法
*/
// 第一种表示方法:任何一个类都有一个隐藏的静态成员方法去获取 Class 实例
Class c1 = A.class;
// 第二种表示方法:利用某一个类的对象的 getClass()方法
Class c2 = a.getClass();
// Class 动态加载一个类
Class c3 = Class.forName("com.fy.reflect.A");
// 一个类只可能是 Class 类的一个实例对象,所以下面的输出都为 true
System.out.println(c1 == c2); //输出 true
System.out.println(c1 == c3); //输出 true
}
}
class A{
}
如何理解动态加载类?
Class.forName("类的全称")
- 不仅表示了类的类类型,还代表了动态加载类
- 一定区分编译和运行
如何理解编译时刻加载类是静态加载类,运行时刻加载类是动态加载类
举个例子,我们 Java 开发者一般选择的 IDE 工具都是 Eclipse 或者 MyEclipse,比如以下代码,我创建了 Eclipse,没创建 MyEclipse 类,书写代码时就会出现错误(即编译出错),导致程序无法运行。也就是即使有了 Eclipse,没有 MyElicpse 也不能开发。但我们实际开发中,只有一个 IDE 工具给我们就能进行开发,不管有没有另外一个。再联想下,某个项目中有几十个功能,若是某个功能有问题其他功能就不能使用么?显然不合理。
public class JavaIDE {
public static void main(String[] args) {
//new 是静态加载类,在编译时都会加载所用到的类
Eclipse e = new Eclipse();
e.coding();
MyEclipse m = new MyEclipse();
m.coding();
}
}
class Eclipse {
public static void coding() {
System.out.println("This is Eclipse");
}
}
因此我们想到,用到某个功能就去加载某个类,即动态加载类。
为了更好的演示效果,希望大家在这里用文本编辑器编写代码,在 cmd 中利用 javac 命令编译、 java 命令运行代码
public class JavaIDE {
public static void main(String[] args) throws Exception {
// 动态加载,在运行时加载类
Class c = Class.forName(args[0]);
// 通过类类型,创建该对象
IdeAble ia = (IdeAble)c.newInstance();
ia.coding();
}
}
在这里,我们通过类类型创建对象时,传统理念是
Eclipse e = (Eclipse)c.newInstance();
但是当我们需要的工具是 MyEclipse 时,这样则不满足功能要求。因此选择一个标准接口,所有功能类都去实现它,创建对象时只需创建接口对象就行。
这样需要什么功能,就去加载某个功能类就行。
interface IdeAble{
public void coding();
}
class Eclipse implements IdeAble{
public void coding() {
System.out.println("This is Eclipse");
}
}
class MyEclipse implements IdeAble{
public void coding() {
System.out.println("This is MyEclipse");
}
}
再在cmd下,编译 JavaIDE 和 Eclipse,在运行。
当我们需要使用 Eclipse 功能时再去编写相应的代码,只要满足 IdeAble 接口标准就行,再运行即可
方法的反射
//获取类的所有方法
public static void getMethods(Object obj) {
Class c = obj.getClass();
// 获取类所有的方法,包括从父类继承而来的
Method[] methods = c.getMethods();
for (Method method : methods) {
// 获取方法的返回类类型
Class returnType = method.getReturnType();
System.out.print(returnType.getName() + " ");
// 获取方法的名称
System.out.print(method.getName() + "(");
// 获取参数类型,得到的是参数列表的类型的类类型
Class[] paramTypes = method.getParameterTypes();
int i = 0;
for (Class class1 : paramTypes) {
if (i == paramTypes.length - 1) {
System.out.print(class1.getName());
} else {
System.out.print(class1.getName() + ",");
}
i++;
}
System.out.println(")");
}
}
成员变量的反射
//获取类的所有成员属性
public static void getField(Object obj) {
Class c = obj.getClass();
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
}
构造函数的反射
//获取类的所有构造方法
public static void getConstructor(Object obj) {
Class c = obj.getClass();
Constructor[] constructors= c.getConstructors();
for (Constructor constructor : constructors) {
System.out.print(constructor.getName()+" (");
Class[] conParams= constructor.getParameterTypes();
int i=0;
for (Class class1 : conParams) {
if (i == conParams.length-1) {
System.out.print(class1.getName());
}else{
System.out.print(class1.getName()+",");
}
i++;
}
System.out.println(")");
}
}