`
hehez
  • 浏览: 12487 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Java的内部类——你知道多少?   

阅读更多
我在写这篇文章之前,我对Java内部类也不是很清楚,只知道简单的应用。前几天有个朋友问我怎么理解Java内部类,我当时就有点傻了,想了半天也没有说出来,我想,如果让大家来回答这个问题,大家该怎么回答呢?我估计,总有一些人回答不上来的,或者说回答的不够完整。我特意查了查,自己又总结了总结,在这给大家分享一下。 在说之前,我先列出几个问题:

    1.外部类(非主类)通过怎样的方式访问内部类?

    2.内部类能不能访问主类私有的属性,为什么?

    3.内部类能不能继承别的类和接口?

    4.内部类能不能是static的?

    5.在主类的方法里面可不可以定义内部类?

    6.初始化主类的时候是不是也把内部类给初始化了?为什么?

    7.怎样写一个匿名的内部类?

  我目前想到的就这些,在我给大家陈述之前,希望大家好好想想,再往下看:

  第一个问题:外部类是怎样引用内部类的?这个问题,我想,可能有的人就会这样写:

  这是内部类:InnerClass.

1 public class MainClass {
2     
3     public class InnerClass{
4         public String name = "name";

6         public String getName() {
7             return name;
8         }
9
10         public void setName(String name) {
11             this.name = name;
12         }
13     }
14 }  
以下是引用:



1 public class CheckClass {
2     public static void main(String[] args) {
3         InnerClass innerClass = new InnerClass();
4         System.out.println(innerClass.getName());
5     }
6 } 

 
如果这样写的话,会报编译错误。那么为什么会报错呢?因为在Java的设计中,如果想访问一个类的内部类,你必须通过宿主类去取它,然后,再对它进行操作,Java就是想这样把内部类给封闭起来的,好吧,正确的写法,我给大家贴出来:

  以下是内部类的写法:

  

1 public class MainClass {
2     public InnerClass getInnerClass() {
3         return new InnerClass();
4     }

6     public class InnerClass {
7         public String name = "name";

9         public String getName() {
10             return name;
11         }
12
13         public void setName(String name) {
14             this.name = name;
15         }
16     }
17 }

  如果你想访问Java内部类,你必须先拿到它的宿主类,这样你才能对内部类进行操作:



1 public class CheckClass {
2     public static void main(String[] args) {
3         MainClass mainClass = new MainClass();
4         System.out.println(mainClass.getInnerClass().getName());
5     }
6 }

  这样的话,编译就不会报错了。







  好了,该回答第二个问题了,就是内部类能不能访问宿主类的私有属性?回答是可以的。如果,你会看JVM的源码的话,你就会看到,在编译内部类调用主类私有变量时,会把它们转换成一种特殊的符号,JVM会把这种符号解析成公有的,然后让内部类调用。代码很简单,我就不贴了。

  接着回答第三个和第四个问题:就是内部类能不能继承别的类和接口?内部类能不能是static的?为什么不能,当然可以,这些并没有什么约束。你自己可以试一下。

  该第五个问题了:在主类的方法里面可不可以定义内部类?其实,这个问题,在我回答第一个问题的时候,已经把答案告诉了大家,就是在getInnerClass()方法里面,不就是new了一个内部类吗。

  第六个问题:初始化主类的时候是不是也把内部类给初始化了?为什么?这个嘛,如果反过来说就对了,因为如果,你想调用内部类,你就得初始化它的主类,因此,你在初始化内部类时就初始化了主类,但是,你初始化主类,如果不是显示的去初始化,你就不可能初始化它的内部类,尽管内部类是在主类的里面。如果,你有时间,你可以到编译的主类文件去看看。

  最后一个问题就是:怎样写一个匿名的内部类?如果大家搞过Java Swing或者Android开发,这个问题对你来说很简单,因为在随便的一些事件里,你就可以定义一个匿名的内部类,然后实现它的方法。不过,为了让更多的人明白,我把代码贴出来,以下是我的代码:

  这是要实现的那个接口:

1 public interface SuperInterface {
2     public void print();
3 }

  以下是主类的代码:

1 public class MainClass {
2     
3     public SuperInterface print(){
4         
5         return new SuperInterface(){

7             public void print() {
8                 System.out.println("Hello Anonymity Interface");
9             }};
10     }
11 }

  其实上面的一段代码就是一个匿名内部类,为什么叫匿名内部类呢?因为,你没有给那个内部类起名字,而是直接实现那个接口,所以叫匿名内部类。

  好吧,我看写的也不少了,不过,可能我还会有疏漏的地方,希望大家能参与进来共同讨论
分享到:
评论
23 楼 laixiang 2011-03-05  
多谢lz,给我上了一课,学习了~~
22 楼 Ben.Sin 2011-03-04  
匿名内部类,一般都用回调的比较多
21 楼 LifeFree 2011-03-04  
cisabc 写道
存在就是有理由的,只是我们不知道这个理由,或者说应用场景。


写GUI程序的时候,Inner Class,那是满天飞。搞WEB应用,使用场景就比较少了。
20 楼 cisabc 2011-03-04  
存在就是有理由的,只是我们不知道这个理由,或者说应用场景。
19 楼 gorymt 2011-03-04  
akunamotata 写道
yangguo 写道
天下本不需内部类,庸人自扰之。


同意

貌似最近也被javaeye扣分了...

同意 +1
and
扣分 +1
18 楼 抢街饭 2011-03-04  
不够详细,希望能再扩展点.
17 楼 ricoyu 2011-03-04  

引用
好啥好啊?这样写的话,还要内部类干嘛?直接放在外面分成两个类好了。

这种不伦不类的写法,分明是为了使用内部类而使用内部类。

你不知道内部类是了解它的外围类的吗? 为什么说“了解”? 因为即便是外围类的private字段, 内部类照样可以访问到,所以请教一下把他们分成两个类以后, 拆分出来的内部类如何去访问外部类的属性? 假设外部类处于安全原因没有提供任何getter/setter方法?
16 楼 mutex_js 2011-03-04  
ricoyu 写道
每个内部类都能独立地继承自一个实现, 所以无论外围类是否已经继承了某个实现, 对于内部类都没有影响。 即内部类有效地实现了多重继承

谢谢指点
15 楼 apei830 2011-03-04  
1.外部类(非主类)通过怎样的方式访问内部类?
前提是内部类,必须不能被定义成private的,否则外部类无法访问(这跟类里的其他普通属性一样)
public class OuterClass {

	public class InnerClass {

	}

	public static class StaticInnerClass {

	}

}

public class TestClass {

	public static void main(String[] args) {
		OuterClass.InnerClass innerObj = new OuterClass().new InnerClass();
		System.out.println(innerObj);

		OuterClass.StaticInnerClass staticInnerObj = new OuterClass.StaticInnerClass();
		System.out.println(staticInnerObj);

	}
}


2.内部类能不能访问主类私有的属性,为什么?
可以
public class OuterClass {

	private String privateOuterField;
	private static String privateStaticOuterField;

	public class InnerClass {
		
		//访问外部类的非静态变量
		public String innerField1 = privateOuterField;//直接访问
		public String innerField2 = OuterClass.this.privateOuterField;

		//访问外部类的静态变量
		public String innerField3 = privateStaticOuterField;//直接访问
		public String innerField4 = OuterClass.privateStaticOuterField;
	}

	public static class StaticInnerClass {
		
		//访问外部类的非静态变量
		public String innerField1 = privateOuterField;//不能直接访问(此行编译会报错)
		public String innerField2 = new OuterClass().privateOuterField;
		
		
		//访问外部类的静态变量
		public String innerField3 = privateStaticOuterField;//直接访问
		public String innerField4 = OuterClass.privateStaticOuterField;
	}

}



3.内部类能不能继承别的类和接口?
肯定能继承别的类,因为所有类首先都是Object的子类
实际上,只要是在宿主类里能访问到的类和接口,都可以让内部类来继承或实现(前提是被继承的类不能使用final定义)

public class SupperClass {

}

public interface SuperInterface {

}

public class OuterClass {

	public class InnerClass extends SupperClass implements SuperInterface {

	}

}


4.内部类能不能是static的?
可以,见1,2

5.在主类的方法里面可不可以定义内部类?
这个问题我和LZ理解的有点不一样
LZ理解成能否在主类方法中使用内部类了
我的理解是在在主类function里可不可以有类的定义?答案是可以的

public class OuterClass {

	public class InnerClass {

	}

	public void function() {

		class FunctionInnerClass {

		}

		FunctionInnerClass funInnerClassInstance = new FunctionInnerClass();
		
		System.out.println(funInnerClassInstance);
	}

}

public class TestClass {

	public static void main(String[] args) {
		new OuterClass().function(); // 执行结果:OuterClass$1FunctionInnerClass@1fb8ee3
	}
}




6.初始化主类的时候是不是也把内部类给初始化了?为什么?
比较同意LZ的观点



7.怎样写一个匿名的内部类?


举个小例子
public class SupperClass {

}

public class OuterClass {

	public SuperInterface superInterface = new SuperInterface() {
		
		@Override
		public void fun() {
			System.out.println(this.getClass());
		}
	};

}

public class TestClass {

	public static void main(String[] args) {
		new OuterClass().superInterface.fun(); // 执行结果:class OuterClass$1
	}
}


在Swing编程,处理事件的时候,匿名内部类的用法比较常见。
其实多线程里也有这样的用法:

public class TestClass {

	public static void main(String[] args) {
		new Thread(new Runnable() {

			@Override
			public void run() {
				System.out.println(this.getClass());
			}
		}).run(); //运行结果:class TestClass$1
	}
}




14 楼 xutao5641745 2011-03-04  
8830417 写道
xutao5641745 写道
楼主:我觉得你讲这么多还是没有讲清楚到底何时用内部类,何时用静态内部类,何时用匿名内部类,何时用局部类。

能不能讲解下???谢谢



我的博客里面写了一篇,但不是很详细,希望对你有帮助!
13 楼 antti 2011-03-04  
内部类在初学java的时候,还好好了解了一下,不过在实际开发中,几年来也没使用过这种!不了解内部类的实用价值
12 楼 hardPass 2011-03-04  
hehez 写道
ricoyu 写道
引用
如果这样写的话,会报编译错误。那么为什么会报错呢?因为在Java的设计中,如果想访问一个类的内部类,你必须通过宿主类去取它,然后,再对它进行操作,Java就是想这样把内部类给封闭起来的,好吧,正确的写法,我给大家贴出来:

  以下是内部类的写法:

  

1 public class MainClass {
2     public InnerClass getInnerClass() {
3         return new InnerClass();
4     }

6     public class InnerClass {
7         public String name = "name";

9         public String getName() {
10             return name;
11         }
12
13         public void setName(String name) {
14             this.name = name;
15         }
16     }
17 }

  如果你想访问Java内部类,你必须先拿到它的宿主类,这样你才能对内部类进行操作:



1 public class CheckClass {
2     public static void main(String[] args) {
3         MainClass mainClass = new MainClass();
4         System.out.println(mainClass.getInnerClass().getName());
5     }
6 }

  这样的话,编译就不会报错了。


不用这么麻烦非要在外围类里面通过方法返回一个内部类的实例吧?
因为你的内部类是public的, 所以可以这样子写
1 public class CheckClass {
2     public static void main(String[] args) {
3         MainClass main = new MainClass();
4         MainClass.InnerClass inner = main.new InnerClass();
5     }
6 }



好的,谢谢



好啥好啊?这样写的话,还要内部类干嘛?直接放在外面分成两个类好了。

这种不伦不类的写法,分明是为了使用内部类而使用内部类。

内部类一般两种用法:
1、内部类为private类型,目的是不被外部发现你用了内部类。
2、static类型,直接 MainClass.InnerClassName 调用。
11 楼 akunamotata 2011-03-04  
yangguo 写道
天下本不需内部类,庸人自扰之。


同意

貌似最近也被javaeye扣分了...
10 楼 shmily2038 2011-03-04  
haiwoo 写道
 最后一个问题就是:怎样写一个匿名的内部类?如果大家搞过Java Swing或者Android开发,这个问题对你来说很简单,因为在随便的一些事件里,你就可以定义一个匿名的内部类,然后实现它的方法。
  内部类最大好处 就是保持跟外部类的生命周期一致,可以通过管理一个类的生命周期来维护俩个类的生命周期在线成池 ,连接池 ,通信套接字 是必然用到的。
这些要求内存管理很高的时候,对类的生命是必须负责的 ,但过多的类不好维护,通常为便于方便维护,就将归纳
并放在一起

学习了
9 楼 haiwoo 2011-03-03  
 最后一个问题就是:怎样写一个匿名的内部类?如果大家搞过Java Swing或者Android开发,这个问题对你来说很简单,因为在随便的一些事件里,你就可以定义一个匿名的内部类,然后实现它的方法。



================================================
没有讲到内部类的真实 目的


  内部类最大好处 就是保持跟外部类的生命周期一致,可以通过管理一个类的生命周期来维护俩个类的生命周期

在线成池 ,连接池 ,通信套接字 是必然用到的
这些要求内存管理很高的时候,对类的生命是必须负责的 ,但过多的类不好维护,通常为便于方便维护,就将归纳
并放在一起
8 楼 hehez 2011-03-03  
ricoyu 写道
引用
如果这样写的话,会报编译错误。那么为什么会报错呢?因为在Java的设计中,如果想访问一个类的内部类,你必须通过宿主类去取它,然后,再对它进行操作,Java就是想这样把内部类给封闭起来的,好吧,正确的写法,我给大家贴出来:

  以下是内部类的写法:

  

1 public class MainClass {
2     public InnerClass getInnerClass() {
3         return new InnerClass();
4     }

6     public class InnerClass {
7         public String name = "name";

9         public String getName() {
10             return name;
11         }
12
13         public void setName(String name) {
14             this.name = name;
15         }
16     }
17 }

  如果你想访问Java内部类,你必须先拿到它的宿主类,这样你才能对内部类进行操作:



1 public class CheckClass {
2     public static void main(String[] args) {
3         MainClass mainClass = new MainClass();
4         System.out.println(mainClass.getInnerClass().getName());
5     }
6 }

  这样的话,编译就不会报错了。


不用这么麻烦非要在外围类里面通过方法返回一个内部类的实例吧?
因为你的内部类是public的, 所以可以这样子写
1 public class CheckClass {
2     public static void main(String[] args) {
3         MainClass main = new MainClass();
4         MainClass.InnerClass inner = main.new InnerClass();
5     }
6 }



好的,谢谢
7 楼 ricoyu 2011-03-03  
引用
如果这样写的话,会报编译错误。那么为什么会报错呢?因为在Java的设计中,如果想访问一个类的内部类,你必须通过宿主类去取它,然后,再对它进行操作,Java就是想这样把内部类给封闭起来的,好吧,正确的写法,我给大家贴出来:

  以下是内部类的写法:

  

1 public class MainClass {
2     public InnerClass getInnerClass() {
3         return new InnerClass();
4     }

6     public class InnerClass {
7         public String name = "name";

9         public String getName() {
10             return name;
11         }
12
13         public void setName(String name) {
14             this.name = name;
15         }
16     }
17 }

  如果你想访问Java内部类,你必须先拿到它的宿主类,这样你才能对内部类进行操作:



1 public class CheckClass {
2     public static void main(String[] args) {
3         MainClass mainClass = new MainClass();
4         System.out.println(mainClass.getInnerClass().getName());
5     }
6 }

  这样的话,编译就不会报错了。


不用这么麻烦非要在外围类里面通过方法返回一个内部类的实例吧?
因为你的内部类是public的, 所以可以这样子写
1 public class CheckClass {
2     public static void main(String[] args) {
3         MainClass main = new MainClass();
4         MainClass.InnerClass inner = main.new InnerClass();
5     }
6 }
6 楼 ricoyu 2011-03-03  
每个内部类都能独立地继承自一个实现, 所以无论外围类是否已经继承了某个实现, 对于内部类都没有影响。 即内部类有效地实现了多重继承
5 楼 yangguo 2011-03-03  
天下本不需内部类,庸人自扰之。
4 楼 pk3589 2011-03-03  
当内部类是 静态内部类的时候 
实例化 外部类的时候 内部类不会跟着初始化吗??????????

相关推荐

    IBM java培训内部资料——Java 常用类讲解.pptx

    IBM java培训内部资料——Java 常用类讲解.pptx

    JAVA基础——Java内部类.ppt

    JAVA基础——Java内部类.ppt

    IBMjava培训内部资料——Java常用类讲解.pptx

    IBMjava培训内部资料——Java常用类讲解.pptx

    浅析Java内部类——成员内部类

    浅析Java内部类——成员内部类 Java内部类是Java语言中的一种特殊的类结构,它可以定义在类内部,而不是独立的类。今天,我们将主要介绍Java成员内部类的相关知识。 什么是内部类 内部类是定义在类内部的类,它...

    详解Java内部类——匿名内部类

    "Java内部类——匿名内部类" Java内部类是一种特殊的类,它可以定义在另一个类的内部,包括成员内部类、静态内部类、局部内部类和匿名内部类等。今天,我们主要来讲解Java中的匿名内部类。 匿名内部类是一种特殊的...

    详细分析Java内部类——局部内部类

    Java内部类之局部内部类 Java内部类是一种特殊的类,它可以嵌套在其他类中,今天我们主要介绍Java局部内部类的相关知识,了解局部内部类的定义、特性和使用场景。 什么是局部内部类? 局部内部类是定义在代码块、...

    浅谈Java内部类——静态内部类

    本文将主要介绍Java静态内部类的相关知识,帮助大家更好地理解和学习Java内部类的相关知识。 什么是静态内部类? ----------------- 在Java中,静态内部类是指使用static关键字修饰的内部类。静态内部类与普通内部...

    Java面试之——代码与编程题

    【Java面试之——代码与编程题】是Java程序员在求职过程中常常遇到的面试环节,主要考察应聘者对Java语言的理解和实际操作能力。面试中,面试官可能会提出各种类型的编程题目,包括但不限于设计模式、继承机制、内部...

    java工具类——验证码(VerifyCode)

    在Java中,我们可以创建一个工具类来生成这种随机验证码,以增强系统安全性。下面我们将深入探讨如何实现这样的验证码工具类及其原理。 1. **验证码生成原理** - 验证码通常由一组随机字符组成,可以是数字、字母...

    Java之——类热加载

    Java之——类热加载 在Java编程中,类的加载是程序运行的重要环节。传统的Java应用程序在启动时,由JVM(Java虚拟机)通过类加载器将类加载到内存中,一旦加载完成,除非程序退出,否则这些类通常不会被重新加载。...

    Java学习笔记——良葛格

    "Java学习笔记——良葛格"是一份专为初学者设计的教程资料,由良葛格精心编写,旨在帮助读者掌握JDK5.0版本的Java基础知识。JDK(Java Development Kit)是Java开发的核心工具集,包含了编译器、调试器和运行环境等...

    Java接口和内部类教程

    在Java中,除了接口之外,还有一个重要的概念——内部类。内部类是在另一个类的内部定义的类,它可以访问外部类的成员变量和方法,即使这些成员是私有的。 内部类分为几种类型:成员内部类、局部内部类、匿名内部类...

    Java实验报告——类、对象的应用

    【实验报告】——Java类与对象的应用 在Java编程中,类是面向对象编程的核心,它代表了现实世界中的实体或者概念。对象则是类的实例,具有特定的属性(成员变量)和行为(成员方法)。本实验旨在通过设计一个贷款类...

    JAVA课程设计——连连看

    在本项目中,"JAVA课程设计——连连看"是一个基于Java编程语言开发的连连看游戏。这个项目展示了Java在游戏开发中的应用,特别是在图形用户界面(GUI)和算法设计方面的运用。下面将详细阐述其中涉及的关键知识点: ...

    Java小程序——动物乐园zoo

    在Java编程语言中,"Java小程序——动物乐园zoo"是一个很好的实践项目,它结合了面向对象编程(Object-Oriented Programming, OOP)和接口(Interface)等核心概念。面向对象是Java的灵魂,它通过类(Class)来定义...

    java 几种内部类(基础)(csdn)————程序.pdf

    Java 内部类是 Java 语言的一个特性,它允许在一个类的定义内部定义另一个类。这种设计模式在处理一些特定情况时非常有用,比如当一个类的实例需要访问另一个类的私有成员,或者需要创建临时性的、特定场景的类实现...

    090830 Java面试题——基础篇60题

    ### Java面试题——基础篇60题解析 #### 1. 作用域 public,private,protected 以及不写时的区别 在Java中,类成员(如变量、方法等)的作用域可以通过不同的修饰符来控制。具体如下: - **public**:公开的,...

    java基础篇——java的起源与演变

    随着时间的推移,Java经历了多次重大版本的更新,从1995年的1.0版本到后续的1.1、1.2、1.3、1.4,直到2004年的Java 5(内部版本号1.5.0),再到后来的Java 6、7、8、9、10和11等。其中,Java 6、7和8在企业级应用中...

Global site tag (gtag.js) - Google Analytics