1 /*****************
2 ***第六章面向对象(下)
3 *******知识点:
4 **************1.内部类
5 ******************1.1 内部类基础
6 ******************1.2 内部类分类和应用
7 **************2.闭包和回调
8 ******************2.1 基础
9 ******************2.2 深入和应用
10 **************3.装箱和拆箱
11 ******************3.1 装箱
12 ******************3.2 拆箱
13
14 */
15
16 public class test6{
17 public static void main(String[] args){
18 showDemo("1.内部类");
19 demoInnerClass();
20
21 showDemo("2.闭包和回调");
22 demoCallBack();
23
24 showDemo("3.装箱和拆箱");
25 demoPackAndUnpack();
26 }
27
28 /*
29 *1.内部类
30 */
31 public static void demoInnerClass(){
32 /**1.1 内部类基础**/
33 //什么是内部类————可以将一个类的定义放在另一个类或者一个方法里面,这个类称为内部类
34
35
36 /**1.2 内部类分类和应用**/
37 //由上面的定义可以得到 内部类分类有:成员内部类、局部内部类、匿名内部类、静态内部类
38
39 //成员内部类
40 //定义————一个类是另一个类的成员 属于对象成员
41 //1.成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
42 //2.当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,
43 // 即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,
44 // 需要以下面的形式进行访问:
45 // 1.外部类.this.成员变量
46 // 2.外部类.this.成员方法
47 //3.在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,
48 // 再通过指向这个对象的引用来访问
49 //4.如果要创建成员内部类的对象,前提是必须存在一个外部类的对象
50 /*
51 class demoMemberInnerClass{
52 private int i,j = 0;
53 public demoMemberInnerClass(int i){
54 this.i = i ;
55 getDrawInstance().drawShape(); //外部类调用内部类方法时必须创建内部类对象才能调用内部类方法
56 System.out.println("外部类成员i:" + this.i); //外部类成员i
57 }
58 private Draw getDrawInstance(){
59 return new Draw();
60 }
61 class Draw{
62 public int i = 3;
63 public void drawShape(){
64 System.out.println("demoMemberInnerClass的私有成员j为:" + j); //可以直接访问外部类成员(包括私有)
65 System.out.println("Draw的私有成员i为:" + i); //因为i同名,故访问的是内部类i
66 System.out.println("demoMemberInnerClass的私有成员i为:" + demoMemberInnerClass.this.i); //i同名,需要访问外部类i 的格式为 外部类.this.成员变量 同名的方法同理可得
67 System.out.println("调用demoMemberInnerClass的私有方法获取Draw的私有成员i为:" + getDrawInstance().returnDrawI()); //可以直接访问外部类方法(包括私有)
68 }
69 public int returnDrawI(){
70 return this.i;
71 }
72 }
73 }
74
75 public class testdemoMemberInnerClass{
76 public static void main(String[] args){
77 //第一种创建内部类方法
78 demoMemberInnerClass dmic = new demoMemberInnerClass();
79 demoMemberInnerClass.Draw draw = dmic.new Draw();
80
81 //第二种创建内部类方法
82 demoMemberInnerClass.Draw draw1 = dmic.getDrawInstance();
83
84 //无论那种方法在创建内部类之前必须存在一个外部类对象
85 //个人比较喜欢第二种 但第二种中的getDrawInstance()需要为public权限
86 }
87 }
88 */
89
90 //局部内部类
91 //定义————定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内
92 //1.局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的
93 //2.只能访问局部final变量
94 /*
95 class demoInnerClass{
96 demoInnerClass(){
97 class demoPartInnerClass{
98 int i = 0;
99 }
100
101 return new demoInnerClass();
102 }
103 }
104 //用得很少。不推荐使用
105 */
106
107
108 //匿名内部类
109 //定义————没有名字的内部类 一般用于代码比较简短的监听事件中
110 //1.匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,
111 // 所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调(常见监听器)
112 //2.匿名内部类也是不能有访问修饰符和static修饰符的
113 //3.只能访问局部final变量
114
115 /*
116 scan_bt.setOnClickListener(new OnClickListener() {
117 public void onClick(View v) {
118 // TODO Auto-generated method stub
119
120 }
121 });//scan_bt 为Button对象
122 */
123
124 //静态内部类
125 //定义————静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static
126 //1.静态内部类是不需要依赖于外部类的
127 //2.静态内部类不能使用外部类的非static成员变量或者方法
128 /*3.静态内部类属于外部类类成员不属于外部类对象成员
129 class demoStaticInnerClass{
130 class Bean1{
131 public int I = 0;
132 public Bean1(){
133 System.out.println("Bean1类的I:" + this.I);
134 }
135 }
136
137 static class Bean2{
138 public int J = 1;
139 public Bean2(){
140 System.out.println("Bean2类的J:" + this.J);
141 }
142 }
143
144
145 class Bean{
146 class Bean3{
147 public int K = 2;
148 public Bean3(){
149 System.out.println("Bean中Bean3类的K:" + this.K);
150 }
151 }
152 }
153 }
154
155 public class testdemoStaticInnerClass{
156 public static void main(String[] args){
157 //初始化Bean1
158 demoStaticInnerClass ds = new demoStaticInnerClass();
159 demoStaticInnerClass.Bean1 ds_bean1 = ds.new Bean1();
160
161 //初始化Bean2
162 demoStaticInnerClass.Bean2 ds_bean2 = new demoStaticInnerClass.Bean2();
163
164 //初始化Bean3
165 demoStaticInnerClass.Bean.Bean3 ds_bean3 = ds.new Bean().new Bean3();
166 }
167
168 }
169
170 //创建静态内部类对象的一般形式为:外部类类名.内部类类名 xxx = new 外部类类名.内部类类名()
171 //创建成员内部类对象的一般形式为:外部类类名.内部类类名 xxx = 外部类对象名.new 内部类类名()
172 */
173
174 }
175
176 /*
177 *2.闭包和回调
178 */
179 public static void demoCallBack(){
180 /**2.1 基础**/
181 //闭包定义————是一种能被调用的对象,用于保存创建它的作用域的信息
182 //回调定义————允许客户类通过内部类引用来调用其外部类的方法
183
184 /**2.2 深入和应用**/
185 /*
186 interface Teacherable{
187 void work() ;
188 }
189
190 class Programmer{
191 private String name;
192 public Programmer() { this.name = "无名氏";}
193 public Programmer(String name) { this.name = name ;}
194 public String getName(){return this.name ;}
195 public void work(){System.out.println("程序员" + name +"正在敲代码");}
196 }
197
198 class TeachProgrammer extends Programmer implements Teacherable{
199 TeachProgrammer(){}
200 TeachProgrammer(String name){ super(name);}
201 private void teach(){System.out.println("程序员" + getName() +"正在教课"); }
202 private class Closure implements Teacherable{
203 public void work(){
204 teach();//内部类调用外部类teach()方法
205 }
206 }
207 public Teacherable getTeacherableInstance(){
208 return new Closure();
209 }
210 }
211
212 public class demoCallBack{
213 public static void main(String[] args){
214 TeachProgrammer tp = new TeachProgrammer();
215 tp.work();//直接调用父类的work方法
216 tp.getTeacherableInstance().work();
217 //表面上调用的是Closure的work方法,实际上是回调TeachableProgrammer的teach方法
218 }
219 }
220
221 //需结合内部类应用知识。本质上就是内部类调用外部类的成员和方法
222 */
223 }
224
225 /*
226 *3.装箱和拆箱
227 */
228 public static void demoPackAndUnpack(){
229 /**3.1 装箱**/
230 //定义————简单来说装箱就是自动将基本数据类型转换成包装器类型
231 //应用
232 Integer i_Integer1 = new Integer(10);
233 Integer i_Integer2 = 10;//装箱 需要是Java SE5之后
234 System.out.println("i_Integer1值为:" + i_Integer1.toString());
235 System.out.println("i_Integer2值为:" + i_Integer2.toString());
236 System.out.println("i_Integer1.equals(i_Integer2):" + i_Integer1.equals(i_Integer2));//返回true
237 System.out.println("i_Integer1==i_Integer2):" + (i_Integer1 == i_Integer2));//返回false
238
239 //总结:
240 //1.上诉返回不同的原因是由于Integer类重写了equals()方法,
241 // 对比的是对象指向的内容 故返回 true == 对比的是对象指向的地址 故返回false
242 //2. 再来分析来equals()和 == 的关系:
243 // 2.1 对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
244 // 如果作用于引用类型的变量,则比较的是所指向的对象的地址
245 // 2.2 对于equals方法,注意:equals方法不能作用于基本数据类型的变量
246 // 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址
247 // 诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
248
249
250
251
252 /**3.2 拆箱**/
253 //定义————简单来说拆箱就是自动将包装器类型转换成基本数据类型
254 //应用
255 int i_a = i_Integer2; //拆箱
256 System.out.println("i_a值为:" + i_a);
257
258 //思考:
259 //1.自动装箱实现原理————Integer i_Integer2 = 10; 等同于 Integer i_Integer2 = Integer.valueOf(10);
260 //2.自动拆箱实现原理————int i_a = i_Integer2; 等同于 int i_a = i_Integer2.intValue();
261 //3.对比两种方式:
262 // Integer i_Integer1 = new Integer(10); 和 Integer i_Integer2 = 10;
263 // 1.前者不会出发自动装箱的过程 后者会
264 // 2.从执行效率和资源占用上来说。在一般情况下后者要优于前者(不绝对)
265 }
266 /*
267 * 抽取打印演示函数 用于打印演示功能提示
268 */
269 public static void showDemo(String demoStr){
270 System.out.println("演示:" + demoStr);
271 }
272 }