Class 类
面向对象的世界里,万事万物都是对象,类也是对象。在 Java 中,除 静态成员 和 普通数据类型 不是对象,其他皆为对象。
其中定义的各种类,是 java.lang.Class 类的实例对象
类对象的表示
1 | public class Test { |
动态加载类与静态加载类
静态加载类: 编译时刻加载的类就是静态加载类,new 类名 出来的就是静态加载类,编译时刻就需要加载可能使用的所有的类。
动态加载类: 运行时刻加载的类就是动态加载类,看下面的例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31// 定义借口,同意标准
interface Animalale {
public void run();
}
// 定义类, 实现统一标准
class Dog implements Animalale {
public void run() {
System.out.println("dog running.");
}
}
public class Test {
public static void main(String[] args) {
try {
// 动态加载类, 运行时刻加载
Class c1 = Class.forName[args[0]]
// 通过类的类类型,去创建实例对象,
Animalale animal = (Animalale) c1.newInstance();
animal.run();
}
catch (Exception e) {
e.printStackTrace()
}
}
}
// 命令行输入
java test Dog
// 输出
dog running.
上面的代码编译后,如有新的动物加入,只需要新写一个类实现 Animal 接口,编译这个新的类即可,原来的代码不需要改动。开发过程中,功能性的类都可以通过这种动态加载方式实现。
数据类型的类类型
1 | // void 关键字 和 基本数据类型 都有类类型 |
Class 类的常用函数
1 |
|
方法反射基本操作
通过 Method.invoke(实例对象,[参数列表]) 进行 方法反射操作1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52public class MethodDemo1 {
public static void main(String[] args) {
// 获取 print(int,int)方法,先获取类类型
A a1 = new A();
Class c = a1.getClass();
/*
* 获取方法,由方法名和参数列表唯一决定一个方法
* getMethod() // 获取所有 public 类型的成员方法
* getDelcaredMethod() // 获取该类所有自己的声明的成员方法,不论访问权限
*/
try {
// 两种方式获取方法对象,效果一样
//Method m = c.getMethod("print", new Class[]{int.class,int.class});
Method m = c.getMethod("print", int.class,int.class);
// 方法反射操作
// 下面两个参数传递方式,效果一样, o 就是 print 方法的返回值,如没有返回值, o 就是 null
//Object o = m.invoke(a1,new Object[]{10,20});
Object o = m.invoke(a1, 10,20);
上面通过方法反射操作和 通过 类的实例对象 直接调用,效果一样
//a1.print(10, 20);
System.out.println("==================");
// 获取参数为 String 类型的 print(String,String)
//Method m1 = c.getMethod("print", new Class[]{String.class,String.class});
Method m1 = c.getMethod("print",String.class,String.class);
//a1.print("hello", "WORLD");
o = m1.invoke(a1, "hello","WORLD");
System.out.println("===================");
// 获取 无参数的 print(String,String)
// Method m2 = c.getMethod("print", new Class[]{});
Method m2 = c.getMethod("print");
// 两种调用方式,效果一样
// m2.invoke(a1, new Object[]{});
m2.invoke(a1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class A{
public void print(){
System.out.println("helloworld");
}
public void print(int a,int b){
System.out.println(a+b);
}
public void print(String a,String b){
System.out.println(a.toUpperCase()+","+b.toLowerCase());
}
}
深入理解 Java 泛型
看下面实例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public static void main(String[] args) {
ArrayList list = new ArrayList();
ArrayList<String> list1 = new ArrayList<String>();
list1.add("hello");
//list1.add(20); // 编译出错, 不能向 String 集合中加入 整型数据
Class c1 = list.getClass();
Class c2 = list1.getClass();
System.out.println(c1 == c2); // 返回结果: true
// 上面说明, 编译之后的集合的泛型是去泛型化的,
// 集合的泛型,目的是防止输入错误,也就是泛型只在编译阶段有效,
// 编译之后就无效了
// 而反射是在 运行时刻加载,通过反射,我们可以绕过泛型的编译限制,如下
try {
Method m = c2.getMethod("add", Object.class);
m.invoke(list1, 20); // 泛型绕过编译,绕过泛型,加入集合
System.out.println(list1.size());
System.out.println(list1);
// 注意此刻 不能 foreach 遍历,遍历报错,类型不对
/*
for (String string : list1) {
System.out.println(string);
}
*/
} catch (Exception e) {
e.printStackTrace();
}
}