面向对象基础(六)[内部类]
来源:互联网 发布:制作课件的软件 编辑:程序博客网 时间:2024/05/22 17:27
转自:http://blog.csdn.net/jiangxinyu/article/details/8177326
本讲内容:内部类
Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类。内部类又分为:常规内部类、局部内部类、匿名内部类和静态嵌套类四种。我们内部类的知识在Android手机开发中经常用到。
一、常规内部类
所谓常规内部类,或者说内部类,指的就是除去后面三种之外的内部类(这算什么解释。。。)
先写一个最简单的内部类的例子,大家感觉一下:
1
public
class
Outer {
2
public
class
Inner{
3
}
4
}
编译一下,我们看到目录中出现了两个class文件,其中有一个文件名叫做Outer$Inner.class,带了一个$符号,这个特点让我们很容易的认出来这是内部类编译后的class文件。
再写一个稍微复杂一点的内部类:
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();的写法
二、局部内部类
我们也可以把类定义在方法内部,这时候我们称这个类叫局部内部类。
我们再看一个例子:
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修饰以后就可以用了,我打算专门在番外篇里专门写一篇博客给你讲清楚,先记住吧。
三、匿名内部类
当我们把内部类的定义和声明写到一起时,就不用给这个类起个类名而是直接使用了,这种形式的内部类根本就没有类名,因此我们叫它匿名内部类。
我们再看一个有趣的例子:
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(){ … } 的方式把声明类的过程和创建类的实例的过程合二为一。
- 匿名内部类可以是某个类的继承子类也可以是某个接口的实现类。
好吧我们再看一个例子,方法参数内的匿名内部类:
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修饰时,我们称之为静态嵌套类或者说静态内部类。
上面的例子里其实我们已经看到过静态嵌套类了,下面我们再举一个例子:
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中应用的非常多,理解和使用好显得蛮重要。好了,本讲就到这里。
如何应用Java的静态内部类
http://java.chinaitlab.com/oop/787330.html//调用静态内部类的静态方法
java 静态内部类的使用
http://blog.csdn.net/xys_777/article/details/6755836
- package Chapter10;
- public class StaticInternal {
- private static String name = "\"聂庆亮\"";
- public static void setStatic(String n) { // 外部类的非静态方法
- System.out.println("[现在访问的是外部类的静态方法!]");
- name = n;
- }
- static class InnerClass_2 { // 静态内部类开始
- String address, mail; // 声明String类型变量
- long phoneNum; // 声明long类型变量
- int qq; // 声明int类型变量
- static void getStatic() { // 静态内部类的静态方法
- System.out.println("[访问外部类的静态变量] name = " + name);
- setStatic("尹继平"); // 访问外部类的静态方法
- }
- // 静态内部类的非静态方法
- public void setString(String address, String mail) {
- System.out.println("1.静态内部类的带String型参数的非静态主法");
- this.address = address;
- this.mail = mail;
- }
- public void setInt(long phoneNum, int qq) {
- System.out.println("2.静态内部类的带int型参数的非静态主法!");
- this.phoneNum = phoneNum;
- this.qq = qq;
- }
- } // 静态内部类结束
- public void setValue() { // 外部类访问静态内部类的静态成员:内部类.静态成员
- InnerClass_2.getStatic(); // 访问静态内部类的静态方法
- InnerClass_2 inner = new InnerClass_2(); // 实例化对象
- inner.setString("北京昌平区沙河镇", "yinjiping@sina.com"); // 访问静态内部类的非静态方法
- inner.setInt(89653310, 313557706);
- System.out.println("\n外部类访问静态内部类的结果如下:");
- System.out.println("姓名:" + this.name);
- System.out.println("住址:" + inner.address);
- System.out.println("联系电话" + inner.phoneNum);
- System.out.println("E-mail:" + inner.mail);
- System.out.println("QQ号码:" + inner.qq);
- }
- public static void main(String[] args) { // java程序主入口处
- StaticInternal sin = new StaticInternal();
- sin.setValue(); // 调用方法
- }
- }
Java内部类与静态内部类
http://hi.baidu.com/zhumulangma/item/bcd478c140427b2cef466532
定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类可以声明public、protected、private等访问限制,可以声明为abstract的供其他内部类或外部类继承与扩展,或者声明为static、final的,也可以实现特定的接口。外部类按常规的类访问方式使用内部类,唯一的差别是外部类可以访问内部类的所有方法与属性,包括私有方法与属性。
(1)创建实例
OutClass.InnerClass obj = outClassInstance.new InnerClass(); //注意是外部类实例.new,内部类
AAA.StaticInner in = new AAA.StaticInner();//注意是外部类本身,静态内部类
(2)内部类中的this
内部类中的this与其他类一样是指的本身。创建内部类对象时,它会与创造它的外围对象有了某种联系,于是能访问外围类的所有成员,不需任何特殊条件,可理解为内部类链接到外部类。 用外部类创建内部类对象时,此内部类对象会秘密的捕获一个指向外部类的引用,于是,可以通过这个引用来访问外围类的成员。
(3)外部类访问内部类
内部类类似外部类的属性,因此访问内部类对象时总是需要一个创建好的外部类对象。内部类对象通过‘外部类名.this.xxx’的形式访问外部类的属性与方法。如:
System.out.println("Print in inner Outer.index=" + pouter.this.index);
System.out.println("Print in inner Inner.index=" + this.index);
(4)内部类向上转型
内部类也可以和普通类一样拥有向上转型的特性。将内部类向上转型为基类型,尤其是接口时,内部类就有了用武之地。如果内部类是private的,只可以被它的外部类问,从而完全隐藏实现的细节。
(5)方法内的类
方法内创建的类(注意方法中也能定义类),不能加访问修饰符。另外,方法内部的类也不是在调用方法时才会创建的,它们一样也被事先编译了。
(6)静态内部类
定义静态内部类:在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。
通常称为嵌套类,当内部类是static时,意味着:
[1]要创建嵌套类的对象,并不需要其外围类的对象;
[2]不能从嵌套类的对象中访问非静态的外围类对象(不能够从静态内部类的对象中访问外部类的非静态成员);
嵌套类与普通的内部类还有一个区别:普通内部类的字段的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段,也不能包含嵌套类。但是在嵌套类里可以包含所有这些东西。也就是说,在非静态内部类中不可以声明静态成员,只有将某个内部类修饰为静态类,然后才能够在这个类中定义静态的成员变量与成员方法。
另外,在创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上。普通非静态内部类的对象是依附在外部类对象之中的,要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。静态类和方法只属于类本身,并不属于该类的对象,更不属于其他外部类的对象。
(7)内部类标识符
每个类会产生一个.class文件,文件名即为类名。同样,内部类也会产生这么一个.class文件,但是它的名称却不是内部类的类名,而是有着严格的限制:外围类的名字,加上$,再加上内部类名字。
(8)为何要用内部类?
1. 内部类一般只为其外部类使用;
2. 内部类提供了某种进入外部类的窗户;
3. 也是最吸引人的原因,每个内部类都能独立地继承一个接口,而无论外部类是否已经继承了某个接口。因此,内部类使多重继承的解决方案变得更加完整。
- 面向对象基础(六)[内部类]
- Java基础第十二讲:面向对象基础(六)[内部类]
- 面向对象基础(内部类)
- 理解面向对象编程(六)-内部类
- java基础3--面向对象(上)(内部类)
- Java基础--面向对象(内部类、异常)
- Java-面向对象(基础编)--内部类
- JAVA面向对象基础:内部类
- Java面向对象基础--内部类
- 面向对象--内部类
- 面向对象-内部类
- 面向对象-内部类
- 面向对象--内部类
- 面向对象基础续3(对象数组、内部类)
- 面向对象(六)之内部类详解
- 面向对象(下) 多态,内部类
- 面向对象(内部类) 异常 包
- 面向对象(匿名内部类)
- mysqldump 参数详解
- 03-修整素材
- Apache log 日志分析
- linux进程内存布局(转)
- ARMv8(aarch64)页表建立过程详细分析
- 面向对象基础(六)[内部类]
- [LDD3阅读笔记] 与硬件通信
- 直接删除undo及temp表空间文件后的数据库恢复一例
- linux 时钟
- ubuntu搭建git服务器和心得体会
- CKeditor的引用
- CCNA学习笔记1
- 编码操练招式——网球计分
- 使用netstat和awk命令来统计网络连接数