黑马程序员技术交流社区
标题: 内部类 [打印本页]
作者: 汪龙 时间: 2014-4-10 20:59
标题: 内部类
什么是内部类?Static Nested Class 和 Inner Class的不同。
作者: qiubaoyang 时间: 2014-4-10 21:03
内部类就是在一个类的内部定义的类,内部类中不能定义静态成员(静态成员不是对象的特性,只是为了找一个容身之处,所以需要放到一个类中而已,这么一点小事,你还要把它放到类内部的一个类中,过分了啊!提供内部类,不是为让你干这种事情,无聊,不让你干。我想可能是既然静态成员类似c语言的全局变量,而内部类通常是用于创建内部对象用的,所以,把“全局变量”放在内部类中就是毫无意义的事情,既然是毫无意义的事情,就应该被禁止),内部类可以直接访问外部类中的成员变量,内部类可以定义在外部类的方法外面,也可以定义在外部类的方法体中,如下所示:
- public class Outer
- {
- int out_x = 0;
- public void method()
- {
- Inner1 inner1 = new Inner1();
- public class Inner2 //在方法体内部定义的内部类
- {
- public method()
- {
- out_x = 3;
- }
- }
- Inner2 inner2 = new Inner2();
- }
-
- public class Inner1 //在方法体外面定义的内部类
- {
- }
-
- }
复制代码
在方法体外面定义的内部类的访问类型可以是public,protecte,默认的,private等4种类型,这就好像类中定义的成员变量有4种访问类型一样,它们决定这个内部类的定义对其他类是否可见;对于这种情况,我们也可以在外面创建内部类的实例对象,创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象,代码如下:
Outer outer = new Outer();
Outer.Inner1 inner1 = outer.new Innner1();
在方法内部定义的内部类前面不能有访问类型修饰符,就好像方法中定义的局部变量一样,但这种内部类的前面可以使用final或abstract修饰符。这种内部类对其他类是不可见的其他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问。这种内部类必须是先定义,后使用,即内部类的定义代码必须出现在使用该类之前,这与方法中的局部变量必须先定义后使用的道理也是一样的。这种内部类可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符。
对于这些细节,只要在eclipse写代码试试,根据开发工具提示的各类错误信息就可以马上了解到。
在方法体内部还可以采用如下语法来创建一种匿名内部类,即定义某一接口或类的子类的同时,还创建了该子类的实例对象,无需为该子类定义名称:
- public class Outer
- {
- public void start()
- {
- new Thread(
- new Runable(){
- public void run(){};
- }
- ).start();
- }
- }
复制代码
最后,在方法外部定义的内部类前面可以加上static关键字,从而成为Static Nested Class,它不再具有内部类的特性,所有,从狭义上讲,它不是内部类。Static Nested Class与普通类在运行时的行为和功能上没有什么区别,只是在编程引用时的语法上有一些差别,它可以定义成public、protected、默认的、private等多种类型,而普通类只能定义成public和默认的这两种类型。在外面引用Static Nested Class类的名称为“外部类名.内部类名”。在外面不需要创建外部类的实例对象,就可以直接创建Static Nested Class,例如,假设Inner是定义在Outer类中的Static Nested Class,那么可以使用如下语句创建Inner类:
Outer.Inner inner = new Outer.Inner();
由于static Nested Class不依赖于外部类的实例对象,所以,static Nested Class能访问外部类的非static成员变量。当在外部类中访问Static Nested Class时,可以直接使用Static Nested Class的名字,而不需要加上外部类的名字了,在Static Nested Class中也可以直接引用外部类的static的成员变量,不需要加上外部类的名字。
在静态方法中定义的内部类也是Static Nested Class,这时候不能在类前面加static关键字,静态方法中的Static Nested Class与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。
作者: 沫然 时间: 2014-4-10 22:51
本帖最后由 沫然 于 2014-4-10 22:53 编辑
Nested Class (一般是C++的说法),InnerClass (一般是JAVA的说法)。
Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。
Nested class分为静态Static nestedclass 的和非静态的 inner class,
静态的Static nested class是不可以直接调用它的外部类enclosing class的,但是可以通过外部类的引用来调用,就像你在一个类中写了main方法一样。
非静态类inner class 可以自由的引用外部类的属性和方法,但是它与一个实例绑定在了一起,不可以定义静态的属性、方法。
Inner Class(内部类)定义在类中的类。
Nested Class(嵌套类)是静态(static)内部类。
1. 要创建嵌套类的对象,并不需要其外围类的对象。
2. 不能从嵌套类的对象中访问非静态的外围类对象。
Anonymous Inner Class (匿名内部类)匿名的内部类是没有名字的内部类。
匿名的内部类不能extends(继承)其它类,但一个内部类可以作为一个接口,由另一个内部类实现。
嵌套类可以作为接口的内部类。正常情况下,你不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分,因为它是static 的。只是将嵌套类置于接口的命名空间内,这并不违反接口的规则。
静态方法是不能继承的,因为它是静态的,所谓静态当然是时间和空间的静止喽.
然后final是java里面定义的,不能被重载的函数。
java里面的函数如果没有特别标识,只要在子类中定义了一个同名的函数,那么父类的函数就被重载掉了。如果new一个子类的对象给父类再调用这个函数,就是调用子类的了。只有new的是父类的调的才是父类的。
java里面没有virtual的说法,因为不是final或static就是virtual的。
abstract是虚函数,自然不可能是final的,同时如上所说,static是不能被重载只能被覆盖的,所以也不可以是abstract的。
在使用匿名内部类时,要记住以下几个原则:
·匿名内部类不能有构造方法。
·匿名内部类不能定义任何静态成员、方法和类。
·匿名内部类不能是public,protected,private,static。
·只能创建匿名内部类的一个实例。
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
匿名类和内部类中的中的this :
有时候,我们会用到一些内部类和匿名类。当在匿名类中用this时,这个this则指的是匿名类或内部类本身。这时如果我们要使用外部类的方法和变量的话,则应该加上外部类的类名。
- /**
- *
- * 普通内部类持有对外部类的一个引用, 静态内部类却没有
- *
- * @author howard
- */
- public class OutterClass {
-
- /*
- * this is static nested class
- */
- private static class StaticNestedClass {
- private void yell() {
- System.out.println(this.toString());
- // OutterClass.this.yell();//静态内部类实例没有外部类实例的引用
- }
- }
-
- /*
- * this is inner class
- */
- private class InnerClass {
- private void yell() {
- System.out.println(this.toString());
- OutterClass.this.yell();//内部类实例显式使用外部类实例的方式
- }
- }
-
- private void yell() {
- System.out.println( this.toString());
- }
-
- private void run() {
- /*
- * this is local class
- */
- class LocalClass {
- public void yell(){
- System.out.println(this.toString());
- }
- }
- /*
- * this is anonymous class
- */
- new Object() {
- public void yell(){
- System.out.println(this.toString());
- }
- }.yell();
- LocalClass lc=new LocalClass();
- InnerClass ic = new InnerClass();
- StaticNestedClass sc=new StaticNestedClass();
- lc.yell();
- ic.yell();
- sc.yell();
- }
-
- public static void main(String[] args) {
- OutterClass oc = new OutterClass();
- oc.run();
- }
- }
复制代码
仔细分析如上代码,可以得出一个结论,所有的内部类,Local
内部类,匿名内部类都可以直接访问外面的封装类的实例变量和方法。而静态嵌套类则不能。
调试代码可以发现,内部类,Local内部类,匿名内部类的实例都持有一个外部封装类实例的隐式引用; 而java对象序列化要求对象里所有的对象成员都实现序列化接口。
所以,如果只有内部类实现序列化,而外部封装类没有实现序列化接口,就会在对内部类进行序列化的时候报出异常。
作者: 请备注 时间: 2014-4-11 10:24
内部类 就是类中类,
class Outer
{
class Inner
{
}
} 其他的我都省了只是为了方便你理解看懂。
作者: 也许依然 时间: 2014-4-11 12:27
内部类的访问规则:
1,内部类可以直接访问外部类中的成员,包括私有
之所以可以直接访问内部类中的成员,是因为内部类持有了一个外部类的引用 。格式:外部类名.this
2,外部类要访问内部类,必须建立内部对象
访问格式:
1,当内部类定义在外部类的成员位置上,也非私有,可以在外部其他类中直接建立内部类对象
格式:
外部类名.内部类名 变量名 = 外部对象.内部对象
Outer.Inner in = new Outer().new Inner();
2,当内部类在成员位置上,就可以被成员修饰符所修饰
比如private:将内部类在外部类中进行封装
static:内部类就具备了静态的特性
当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问权限
在外部其他类中,如何直接访问静态内部类的非静态成员呢
new Outer.Inner().functin();
在外部其他类中,如何直接访问静态内部类的静态成员呢
Outer.Inner.function();
注意当内部类定义了静态成员,该内部类必须是静态的
当外部类中的静态方法访问内部类时,内部类也必须是static的
当描述事物时,事物的内部还有事物,该事物用内部类描述
因为内部事物在使用外部事物的内容。
- class Outer
- {
- private static int x;
- static class Inner
- {
- static void fuction()
- {
- int x = 4;
- System.out.println("inner"+ x);
- }
- }
- static class Inner2
- {
- void show()
- {
- System.out.println("show run");
- }
- }
- public static void method()
- {
- //Inner in = new Inner();
- //in.fuction();
- new Inner2().show();
- }
- }
- class InnerClassDemo
- {
- public static void main(String[] args)
- {
- Outer out = new Outer();
- out.method();
- new Outer.Inner().fuction();
- //直接访问内部类的成员
- //Outer.Inner in = new Outer().new Inner();
- //in.fuction();
- }
- }
复制代码
内部类定义在局部时
1,不可以被成员修饰符修饰
2,可以直接访问外部类中的成员,因为还持有外部类的引用,但是不可以访问它所在的局部的变量
只能访问被final修饰的局部变量
匿名内部类:
1,匿名内部类其实就是内部类的简写格式
2,定义匿名内部类的前提:
内部类必须是继承一个类或实现接口
3,匿名内部类的格式:new 父类或者接口() {定义子类的内容}
4,其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象
5,匿名内部类中定义的方法最好不超过三个
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |