黑马程序员_java内部类
将一个类定义在另一个类的里面,对里面那个类就称为内部类,内部类是一种非常有用的特性,因为它允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。然而必须要了解,内部类与组合是完全不同的概念,这一点很重要,内部类分为:成员内部类、静态嵌套类、局部内部类、匿名内部类。
内部类的共性:
(1)、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
(2)、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。
(3)、内部类声明成静态的,就不能随便的访问外部类的成员变量仍然是只能访问外部类的静态成员变量成员内部类
成员内部类:(内部类在外部类成员位置上时就称为成员内部类)
class Outer {
int x=1;
class Inner{
int x=2;
public void show(){
int x=3;
System.out.println(x);//打印--------3
System.out.println(this.x);//打印--------2
System.out.println(Outer.this.x);//打印--------1
}
}
}
public class Test{
public static void main(String[] args){
Outer.Inner myInner=new Outer().new Inner();
myInner.show();
}
}
编译上述代码会产生两个文件:Outer.class和Outer$Inner.class,如何来创建成员内部类的对象呢?代码如下:
Outer.Inner myInner=new Outer().new Outer();//外部类名.内部类名 变量名=外部类对象.内部类对象
静态嵌套类:(内部类在外部类成员位置上时就可以被修饰,所以此内部类被static修饰后就成为了静态嵌套类)
静态内部类中可以定义静态或者非静态的成员。从技术上讲,静态嵌套类不属于内部类。因为内部类与外部类共享一种特殊关系,更确切地说是对实例的共享关系。而静态嵌套类则没有上述关系。它只是位置在另一个类的内部,因此也被称为顶级嵌套类。
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法。
class Outer{
static String info="hello world";
static class Inner{
public void show(){
System.out.println(info);
}
}
}
public class Test {
public static void main(String[] args){
Outer.Inner myInner = new Outer.Inner();
myInner.show();
}
}
注意:当内部类中定义了静态成员,该内部类必须是static的。
局部内部类:(内部类定义在局部时就称为局部内部类)
class Outer {
public void doSomething(){
final int NUMBER=4;//注意这里的变量被final修饰了,下面会讲为什么。
class Inner{
public void show(){
System.out.println(NUMBER);
}
}
new Inner().show();//调用此内部类的show方法
}
}
方法内部类注意事项:
1.不可以被成员修饰符修饰
2.可以直接访问外部类中的成员,因为还持有外部中的引用,但是不可以访问它所以的局部中的变量。只能访问被final修饰的局部变量。
匿名内部类(没有名字的局部内部类)
顾名思义,没有名字的局部内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:
1.只用到类的一个实例。
2.类在定义后马上用到。
3.类非常小(SUN推荐是在4行代码以下)
4.给类命名并不会导致你的代码更容易被理解。
在使用匿名内部类时,要记住以下几个原则:
1·匿名内部类不能有构造方法。
2·匿名内部类不能定义任何静态成员、静态方法。
3·匿名内部类不能是public,protected,private,static。
4·只能创建匿名内部类的一个实例。
5·一个匿名内部类一定是在new的后面,格式:new 父类或者接口(){定义子类的内容}
6·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
-----------请看下面的例子:--------
定义匿名内部类的前提:
内部类必须是继承一个类或者实现接口
(案例1)
abstract class Inner{//在这里我定义了一个抽象类
public abstract void show();
}
public class Outer{
public void function(){
new Inner(){//这就是在定义一个匿名内部类,java隐式的继承了这个类。
//所以可以说这个匿名内部类,就是Inner类的子类对象
public void show(){//重写Inner类的show方法
System.out.println("hello world");
}
} .show();//这里是在调用这个匿名对象中的show方法,这就是一种格式,记住就好。
}
}
---------------------代码分割线------------------------
(案例2)
class Inner{//在这里我定义了一个普通类
public void show(){
}
}
public class Outer{
public void function(){
new Inner(){
public void show(){
System.out.println("hello world");
}
} .show();
}
}
---------------------代码分割线------------------------
案例(3)
interface Inner{//在这里我定义了一个接口
public void show(){
}
}
public class Outer{
public void function(){
new Inner(){
public void show(){
System.out.println("hello world");
}
} .show();//在这里我们会发现只能调用一次方法。因为这是匿名的,我们如何把这个匿名对象赋值给一个变量呢?请看案例(4)
}
}
---------------------代码分割线------------------------
class Inner{//在这里我定义了一个普通类
public void show(){
}
}
public class Outer{
public void function(){
Inner myInner=new Inner(){//注意这里与上面案例不同之处,我们将这个匿名对象的内存地址给myInner对象的。现在我们就可以通过myInner来操作这个对象了。
public void show(){
System.out.println("hello world");
}
public void show2(){
System.out.println("你好世界");
}
}
myInner.show();//这么写没有问题。
myInner.show2();//这么写却会报错
因为上面我们说过匿名类其实就是一个匿名的子类对象,在这里Inner类就是这个匿名内部类的父类,上面这个把匿名对象的内存地址给myInner其实就是父类的引用指向了子类的对象
然而父类Inner中却没有show2这个方法。所以会报错。这是多态的知识。
}
}
邮箱:wolaoben7252@qq.com