0%

706内部类+反射

2017年7月6日 上午8:03

成员式内部类-非静态:

1. 生成两个class文件
2. **Outer$Inner.class**
3. Outer.class
4. **内部类的方法和属性可以和外部类相同**

Outer.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public class Outer {
String name;
public void method(){

}

public class Inner{
int age;
String name;
void method(){

}
}
}

成员式内部类-静态

Outer2.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public class Outer2 {
String name;
public void method(){

}

public static class Inner{
int age;
String name;
void method(){

}
}
}

Test1.class

1
2
3
4
5
6
7
8
9
10
11

public class Test1 {

public static void main(String[] args) {
//创建成员式内部类 -- 非静态
Outer.Inner oi = new Outer().new Inner();
//创建成员式内部类 -- 静态
Outer2.Inner oi2 = new Outer2.Inner();
}

}

匿名内部类

Outer3.class

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

public class Outer3 {
String name = "czh";
public void method(final int j){
int x=0;
class Inner{
//内部类使用外部的成员变量
int age = x;
String name2= name;
int k = j;

void method(){
System.out.println("Inner类方法");
}
}

Inner in = new Inner();
in.method();
}

public void method2(){
// Inner in2 = new Inner();
}

}

几点说明:
1. 全局变量name 和 method()中的局部变量可以直接被内部类Inner()使用,因为:name 和 x的作用域包含内部类
2. 内部类Inner的作用域为method()方法中,所以:在method2()中声明Inner类对象是会报错的。
3. java1.8中,method(final int j )中的final可以不用加了

反射

定义:在编译时不确定哪个类被加载,而在程序运行时才加载、
探知、使用。常用于框架中,具体的不会!

反射的操作方式:

  1. 我们平常操作时都是对象.属性/方法对象为主角
  2. 在反射中,属性(Field)方法(Method)构造(Constructor)为主角,他们去【点】原对象对象反而作为了参数
  3. 并且反射还可操作private属性
  4. 总结:换了一种操作类和对象的方式

两种得到类的方式

  1. Class cla=Student.class;
  2. 包名+类名
    1. Class cla = Class.forName(“package1.Student”);

反射常用的Java 类型

  1. Class类—可获取类和类的成员信息
  2. Field类—可访问类的属性
  3. Method类—可调用类的方法
  4. Constructor类—可调用类的构造方法

使用反射的步骤:

  1. 导入java.lang.reflect.*
  2. 获得需要操作的类的Java.lang.Class对象
  3. 调用Class的方法获取Field、Method等对象
  4. 使用反射API进行操作 (设置属性、调用方法)
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//学生类
public class Student {
private String name; //姓名
private int age; //年龄

public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age=age;
}
public String toString(){
return "name is "+name+", age is "+age;
}

}
================================================
//利用反射测试属性的调用
import java.lang.reflect.Field;

public class Test_Student {
public static void main(String[] args) throws Exception{
//创建一个Student对象
Student p=new Student();
//获取Student对应的Class对象
Class cla=Student.class;

//获取Student类的name属性,使用getDeclaredField()方法可获取各种访问级别的属性
Field nameField=cla.getDeclaredField("name");
//设置通过反射访问该Field时取消权限检查
nameField.setAccessible(true);
//调用set()方法为p对象的指定Field设置值
nameField.set(p, "Jack");

//获取Student类的name属性,使用getDeclaredField()方法可获取各种访问级别的属性
Field ageField=cla.getDeclaredField("age");
//设置通过反射访问该Field时取消权限检查
ageField.setAccessible(true);
//调用setInt()方法为p对象的指定Field设置值
ageField.setInt(p, 20);
System.out.println(p);
}

}
==================================================
// 反射中方法的测试
import java.lang.reflect.Method;

public class Test_Method {
public static void main(String[] args) throws Exception{
//获取Student对应的Class对象
Class cla=Student.class;
//创建Student对象
Student p=new Student();
//得到setName方法
Method met1=cla.getMethod("setName", String.class);
//调用setName,为name赋值
met1.invoke(p, "Jack");

//得到setName方法
Method met=cla.getMethod("getName", null);
//调用setName,为name赋值
Object o=met.invoke(p, null);
System.out.println(o);
}

}
==================================================
//反射中构造方法的测试
import java.lang.reflect.Constructor;
import java.util.Date;
public class Test_Constructor {
public static void main(String[] args) throws Exception{

//获取Date对应的Class对象
Class cla=Date.class;
//获取Date中带一个长整形参数的构造方法
Constructor cu=cla.getConstructor(long.class);
//调用Constructor的newInstance()方法创建对象
Date d=(Date)cu.newInstance(1987);
System.out.println(d.toString());

}
}

一个使用反射的例子(数据库连接)

1
2
3
4
5
6
public COnnnection getConnection() throws Exception{
Connection conn = null;
Class.forName("com.mysqk.jdbc.Dirver");
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/<Datebase>","root","123456");
syso("连接数据库成功");
}