Java基础第十二讲:面向对象基础(六)
如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!
Java基础第十二讲:面向对象基础(六)
public class Outer {
public class Inner{
}
}
编译一下,我们看到目录中出现了两个class文件,其中有一个文件名叫做Outer$Inner.class,带了一个$符号,这个特点让我们很容易的认出来这是内部类编译后的class文件。
再写一个稍微复杂一点的内部类:
public class Outer {
private int x=1;
public Outer(){
System.out.println("Outer initial");
}
public class Inner{
public Inner(){
System.out.println("Inner initial");
}
private int x=2;
public void add(){
int x=3;
System.out.println(x);
System.out.println(this.x);
System.out.println(Outer.this.x);
}
}
public static void main(String[] args){
Inner inner = new Outer().new Inner();
inner.add();
}
}
我们编译以后,运行一下看看:
在上面的例子里我们可以清晰的看到:
- 内部类就像一个实例成员一样存在于外部类中。
- 内部类可以访问外部类的所有成员就想访问自己的成员一样没有限制。
- 内部类中的this指的是内部类的实例对象本身,如果要用外部类的实例对象就可以用类名.this的方式获得。
- 内部类对象中不能有静态成员,原因很简单,内部类的实例对象是外部类实例对象的一个成员。
- 在外部类的内部,可以用 Inner inner = new Inner(); 方法直接创建
- 在外部类外部,必须先创建外部类实例,然后再创建内部类实例,除了上面 Inner inner = new Outer().new Inner()的写法以外,还有 Outer outer = new Outer(); Inner inner = outer.new Inner();的写法
public class Outer {
int x =1;
public void doSomething(){
final int y=2;
class Inner{
int x =3;
void print(){
int x=4;
System.out.println(x);
System.out.println(this.x);
System.out.println(Outer.this.x);
System.out.println(y);
}
}
Inner inner = new Inner();
inner.print();
}
public static void main(String[] args){
Outer outer = new Outer();
outer.doSomething();
}
}
运行程序,查看结果:
我们通过上面这里例子也可以看到下面几点:
- 局部内部类的地位和方法内的局部变量的位置类似,因此不能修饰局部变量的修饰符也不能修饰局部内部类,譬如public、private、protected、static、transient等
- 局部内部类只能在声明的方法内是可见的,因此定义局部内部类之后,想用的话就要在方法内直接实例化,记住这里顺序不能反了,一定是要先声明后使用,否则编译器会说找不到。
- 局部内部类不能访问定义它的方法内的局部变量,除非这个变量被定义为final 。
public class Dog {
public interface Pet {
public void beFriendly();
public void play();
}
public static void main(String[] args){
Pet dog = new Pet(){
@Override
public void beFriendly() {
System.out.println("蹭蹭你^_^");
}
@Override
public void play() {
System.out.println("把飞盘叼给你,逼你把飞盘丢出去,然后它再捡回来让你继续扔,连续500次^_^");
}
};
dog.beFriendly();
dog.play();
}
}
编译和运行程序,查看结果:
竟然编译和运行都很正常,我们知道抽象类和接口肯定无法实例化的,因此刚才的例子肯定有点意思:
- 第一匿名内部类可以是个接口,这个没什么好奇怪的哈。
- 第12行到第21行是一个语句,就是定义了一个对象,因此21行大括号后面有个分号。
- 匿名内部类用 new Pet(){ … } 的方式把声明类的过程和创建类的实例的过程合二为一。
- 匿名内部类可以是某个类的继承子类也可以是某个接口的实现类。
public class Dog {
static abstract class Ball {
abstract String getName();
}
void play(Ball b){
System.out.println(b.getName());
}
public static void main(String[] args){
Dog dog = new Dog();
dog.play(new Ball(){
@Override
String getName() {
return "qiu qiu";
}});
}
}
编译和运行以后的截图我就不给你了,返回值就是“qiu qiu”。
从第14行到第18行是一句话,就是执行一个play方法,而这个方法的参数就由一个匿名内部类的实例来提供。
四、静态嵌套类
为了让你感觉舒服一些,我们也把最简单的内部类放在最后讲。
当一个内部类前面用static修饰时,我们称之为静态嵌套类或者说静态内部类。
上面的例子里其实我们已经看到过静态嵌套类了,下面我们再举一个例子:
public class Outer {
static int x =1;
static class Nest {
void print(){
System.out.println("Nest "+x);
}
}
public static void main(String[] args){
Outer.Nest nest = new Outer.Nest();
nest.print();
}
}
因为静态嵌套类和其他静态方法一样只能访问其它静态的成员,而不能访问实例成员。因此静态嵌套类和外部类(封装类)之间的联系就很少了,他们之间可 能也就是命名空间上的一些关联。上面例子中你需要注意的就是静态嵌套类的声明方法 new Outer.Nest() 连续写了两个类名,以至于我们都怀疑前面的Outer是个包名了,好在包名一般都小写的,要不还真分不清……
再强调一遍,内部类在Android中应用的非常多,理解和使用好显得蛮重要。好了,本讲就到这里。
分享至上:分享源头- 分类:
- Java
更新时间:
相关文章
Java基础第九讲:面向对象基础(三)
本讲内容:继承、变量隐藏、方法重写、包、修饰符、this、super 一、继承 1、继承的概念 继承是面向对象的三大特性之一。在语义上继承的意思是照法律或遵照遗嘱接受死者的财 阅读更多…
Java基础第十一讲:面向对象基础(五)
本讲内容:接口 一、为什么要有接口 我们已经知道Java中只支持单继承,或者说不允许多重继承的出现,又可以说一个类只能有一个父类。为了提供类似多重继承的功能,Java提供了接口的 阅读更多…
Java基础第八讲:面向对象基础(二)
本讲内容:成员变量、方法、方法的重载、构造函数 一、用程序讲解小白的故事 小白是一条狗,它心情好的时候会恭喜人发财,它心情差的时候会对路人撒野,吓得路人落荒而逃。下面我们用面向对象的方 阅读更多…
Java基础第十讲:面向对象基础(四)
本讲内容:抽象类、初始化块 一、抽象类 用 abstract 修饰的类定义,我们称之为抽象类,抽象类不能被实例化。 用 abstract 修饰的方法,我们称之为抽象方法,抽象方法 阅读更多…
Java基础第七讲:面向对象基础(一)
本讲内容:面向对象的概念和发展、面向对象的特征 一、面向对象(Object Oriented)编程语言的历史 1950年有个叫做荷兰德的学生作为程序员进入IBM的时候,这个世界上的程序 阅读更多…
