学习Android之内部类
java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类。内部类又分为:常规内部类、局部内部类、匿名内部类和静态嵌套类四种。我们内部类的知识在Android手机开发中经常用到。
一、常规内部类
所谓常规内部类,或者说内部类,指的就是除去后面三种之外的内部类(这算什么解释。。。)
先写一个最简单的内部类的例子,大家感觉一下:
view sourceprint?1 public class Outer {
2 public class Inner{
3 }
4 }
编译一下,我们看到目录中出现了两个class文件,其中有一个文件名叫做Outer$Inner.class,带了一个$符号,这个特点让我们很容易的认出来这是内部类编译后的class文件。
再写一个稍微复杂一点的内部类:
view sourceprint?01 public class Outer {
02
03 private int x=1;
04
05 public Outer(){
06 System.out.println("Outer initial");
07 }
08
09 public class Inner{
10
11 public Inner(){
12 System.out.println("Inner initial");
13 }
14
15 private int x=2;
16
17 public void add(){
18 int x=3;
19 System.out.println(x);
20 System.out.println(this.x);
21 System.out.println(Outer.this.x);
22 }
23
24 }
25
26 public static void main(String[] args){
27 Inner inner = new Outer().new Inner();
28 inner.add();
29 }
30 }
我们编译以后,运行一下看看:
在上面的例子里我们可以清晰的看到:
内部类就像一个实例成员一样存在于外部类中。
内部类可以访问外部类的所有成员就想访问自己的成员一样没有限制。
内部类中的this指的是内部类的实例对象本身,如果要用外部类的实例对象就可以用类名.this的方式获得。
内部类对象中不能有静态成员,原因很简单,内部类的实例对象是外部类实例对象的一个成员。
下面我们再小结一下内部类的创建方法:
在外部类的内部,可以用 Inner inner = new Inner(); 方法直接创建
在外部类外部,必须先创建外部类实例,然后再创建内部类实例,除了上面 Inner inner = new Outer().new Inner()的写法以外,还有 Outer outer = new Outer(); Inner inner = outer.new Inner();的写法
二、局部内部类
我们也可以把类定义在方法内部,这时候我们称这个类叫局部内部类。
我们再看一个例子:
view sourceprint?01 public class Outer {
02
03 int x =1;
04 public void doSomething(){
05 final int y=2;
06 class Inner{
07 int x =3;
08 void print(){
09 int x=4;
10 System.out.println(x);
11 System.out.println(this.x);
12 System.out.println(Outer.this.x);
13 System.out.println(y);
14 }
15 }
16 Inner inner = new Inner();
17 inner.print();
18 }
19
20 public static void main(String[] args){
21 Outer outer = new Outer();
22 outer.doSomething();
23 }
24 }
运行程序,查看结果:
我们通过上面这里例子也可以看到下面几点:
局部内部类的地位和方法内的局部变量的位置类似,因此不能修饰局部变量的修饰符也不能修饰局部内部类,譬如public、private、protected、static、transient等
局部内部类只能在声明的方法内是可见的,因此定义局部内部类之后,想用的话就要在方法内直接实例化,记住这里顺序不能反了,一定是要先声明后使用,否则编译器会说找不到。
局部内部类不能访问定义它的方法内的局部变量,除非这个变量被定义为final 。
是不是有点不好理解?关于为什么用final修饰以后就可以用了,我打算专门在番外篇里专门写一篇博客给你讲清楚,先记住吧。
三、匿名内部类
当我们把内部类的定义和声明写到一起时,就不用给这个类起个类名而是直接使用了,这种形式的内部类根本就没有类名,因此我们叫它匿名内部类。
我们再看一个有趣的例子:
view sourceprint?01 public class Dog {
02
03 public interface Pet {
04
05 public void beFriendly();
06 public void play();
07
08 }
09
10 public static void main(String[] args){
11
12 Pet dog = new Pet(){
13 @Override
14 public void beFriendly() {
15 System.out.println("蹭蹭你^_^");
16 }
17 @Override
18 public void play() {
19 System.out.println("把飞盘叼给你,逼你把飞盘丢出去,然后它再捡回来让你继续扔,连续500次^_^");
20 }
21 };
22
23 dog.beFriendly();
24 dog.play();
25
26 }
27 }
编译和运行程序,查看结果:
竟然编译和运行都很正常,我们知道抽象类和接口肯定无法实例化的,因此刚才的例子肯定有点意思:
第一匿名内部类可以是个接口,这个没什么好奇怪的哈。
第12行到第21行是一个语句,就是定义了一个对象,因此21行大括号后面有个分号。
匿名内部类用 new Pet(){ … } 的方式把声明类的过程和创建类的实例的过程合二为一。
匿名内部类可以是某个类的继承子类也可以是某个接口的实现类。
好吧我们再看一个例子,方法参数内的匿名内部类:
view sourceprint?01 public class Dog {
02
03 static abstract class Ball {
04 abstract String getName();
05 }
06
07 void play(Ball b){
08 System.out.println(b.getName());
09 }
10
11 public static void main(String[] args){
12 Dog dog = new Dog();
13
14 dog.play(new Ball(){
15 @Override
16 String getName() {
17 return "qiu qiu";
18 }});
19 }
20 }
编译和运行以后的截图我就不给你了,返回值就是“qiu qiu”。
从第14行到第18行是一句话,就是执行一个play方法,而这个方法的参数就由一个匿名内部类的实例来提供。
四、静态嵌套类
为了让你感觉舒服一些,我们也把最简单的内部类放在最后讲。
当一个内部类前面用static修饰时,我们称之为静态嵌套类或者说静态内部类。
上面的例子里其实我们已经看到过静态嵌套类了,下面我们再举一个例子:
view sourceprint?01 public class Outer {
02
03 static int x =1;
04
05 static class Nest {
06
07 void print(){
08 System.out.println("Nest "+x);
09 }
10 }
11
12 public static void main(String[] args){
13 Outer.Nest nest = new Outer.Nest();
14 nest.print();
15 }
16 }
因为静态嵌套类和其他静态方法一样只能访问其它静态的成员,而不能访问实例成员。因此静态嵌套类和外部类(封装类)之间的联系就很少了,他们之间可能也就是命名空间上的一些关联。上面例子中你需要注意的就是静态嵌套类的声明方法 new Outer.Nest() 连续写了两个类名,以至于我们都怀疑前面的Outer是个包名了,好在包名一般都小写的,要不还真分不清……
再强调一遍,内部类在Android中应用的非常多,理解和使用好显得蛮重要。
匿名类不等同于匿名内部类
匿名类不等同于匿名内部类,后者也经常使用,匿名内部类是内部类的一种,使用的时候更加简洁,但是不是任何情况下都需要使用。
在thinking in java 3th 是这么阐述的:
简单地说:匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较
合适的:
·只用到类的一个实例。
·类在定义后马上用到。
·类非常小(SUN推荐是在4行代码以下)
·给类命名并不会导致你的代码更容易被理解。
在使用匿名内部类时,要记住以下几个原则:
·匿名内部类不能有构造方法。
·匿名内部类不能定义任何静态成员、方法和类。
·匿名内部类不能是public,protected,private,static。
·只能创建匿名内部类的一个实例。
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
学习Android之内部类的更多相关文章
- java学习面向对象之内部类
什么是面向对象内部类呢?所谓的内部类,即从字面意义上来理解的话,就是把类放到类当中. 那么内部类都有什么特点呢? 1.内部类可以访问包裹他的类的成员. 2.如果包裹他的类想访问被其包裹的类的话就得实例 ...
- JavaSE 学习笔记之内部类(九)
内部类:如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象.这时,为了方便设计和访问,直接将A类定义在B类中.就可以了.A类就称为内部类.内部类可以直接访问外部类中的成员.而外部类想要访问内 ...
- 学习android学习必备的java基础知识--四大内部类
学习android必备的java基础知识--四大内部类 今天学习android课程,因为我的主专业是JAVA,但是兴趣班却有这其他专业的同学,学习android 需要具备一些java的基础知识,因此就 ...
- 想学习Android开发
最近被别人说知识面窄,心里受伤了.准备学学Android开发,如果能在手机里运行自己写的app,那是多么high ~~~ Android开发需要看什么资料呢? 说明:本人一直从事windows下的C+ ...
- 从零开始学习Android(一)Android环境的搭建
好久没有开始写博客了,最近开始学习Android,所以想把学习的笔记都一一记录下来.一来是方便自己以后资料的查询,其次也是给Android新手朋友进行学习使用,再次也希 望得到高手的指点.废话少说,我 ...
- 《IT蓝豹》吹雪花demo,学习android传感器
吹雪花demo,学习android传感器 吹雪花demo,学习android传感器,嘴巴对着手机底部吹一下就会出现飘着雪花效果. 算是学习android传感器效果.本例子主要是通过android.me ...
- 一起来学习Android自定义控件1
概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会 ...
- 10个很棒的学习Android 开发的网站(转)
看到江湖旅人 写的<10个很棒的学习iOS开发的网站 - 简书>,所以就忍不住写Android 啦,也希望对大家有帮助.我推荐的网站,都是我在学习Android 开发过程中发现的好网站,给 ...
- 深入学习Android有关网络连接的内容
基于实际项目中碰到的些许问题,开始重新深入学习Android网络连接有关知识. Android的4.1.2版本的AndroidHttpClient模块setSoTimeout之后实际超时时间和设置的时 ...
随机推荐
- xampp下安装yii框架下遇到的问题
用yii框架来生成web目录是输入E:\xampp\htdocs\yii\framework/yiic webapp E:\xampp\htdocs\web 时提示php不是内部命令,也不是... 这 ...
- Python在Windows下开发环境配置汇总
最近比较关注学习Python方面的资料和课程,由于Python本身基本都是在Linux下开发,本人windows用习惯了初用Linux各种别扭啊. 下面将我在配置Windows环境下的禁言写出来,与大 ...
- C++数据类型总结
关键字:C++, 数据类型, VS2015. OS:Windows 10. ANSI C/C++基本数据类型: Type Size 数值范围 无值型void 0 byte 无值域 布尔型bool 1 ...
- C语言socket编程--每日签到
前几天写了个python的每日签到,你运行还得借助crontab,很是不爽.....正好前几天看了个关于c编写daemon进程,加上自己那点可怜的socket知识,于是我们重操旧页,C语言版的每日签到 ...
- ubuntu 设置显示器的亮度
ubuntu电脑重新启动后,亮度都变成了最亮.似乎也没胡地方可以设置.只好通过写个脚本来做这个事了. # -*- coding: utf-8 -*- import dbus bus = dbus.Se ...
- mac 下 sphinx + mysql + php 实现全文搜索(xampp)(1)
原理: 使用sphinx 中的indexer 生成索引数据 service/web 端 利用searched 调用索引数据 步骤: 下载 sphinx: 下载地址:http://sphinxsea ...
- 模式对话框里的CheckedChanged事件
问题: 模式对话框里的CheckedChanged事件不被触发: 解决方法: 一.先不直接showModalDialog出要的页面,而是要放一个中单页面 window.showModalDialo ...
- 内置对象之Cookie
if (!this.IsPostBack) { try { HttpCookie MyCookie = new HttpCookie("MyCookie"); MyCookie.V ...
- 通过物理模型生成Java代码
通过物理模型生成Java代码 软件开发过程中,我们一般是先针对数据库建模,物理建模完成后,生成数据库表,编码阶段的时候我们会针对数据库表生成大量的Javaeban或者是实体类 Powertdesign ...
- Cocos2dx隐藏iOS7状态栏】通过添加Plist Key隐藏iOS7状态栏
本站文章均为李华明Himi原创,转载务必在明显处注明:(作者新浪微博:@李华明Himi) 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/%e9%9a% ...