⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 java04_13.htm

📁 JAVA的课件
💻 HTM
字号:
<html>

<head>
<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Java程序设计</title>
</head>

<body background="Bg.gif">

<p align="center"><font size="5"><b>§4.13 内部类</b></font></p>   
   
<p align="left">&nbsp;&nbsp;&nbsp; 内部类是由Java1.1之后提出的一种新型的类。我们前面所学习的类都是定义在包中,可以说是顶层类。而内部类则是可以<b>定义</b>在另外一个类的里面,为了便于描述,我们将包含了内部类的这个类称为<b>外部类</b>。这是对Java的重大改进。内部类对于简化事件处理非常有用。</p>   
<p align="left">&nbsp;&nbsp;&nbsp;    
和一般的类相同,内部类也是由成员变量和成员方法组成,它的定义和使用与普通类也很相似,但有一些细微的区别。</p>   
<p align="left">&nbsp;&nbsp;&nbsp;    
严格来说,内部类也分为三种:嵌入类(nested)、内部成员类(inner)和本地类。当类的前面有static修饰符时,它就是嵌入类,嵌入类只能和外部类的成员并列,不能定义在方法中。如果类和外部类的成员是并列定义的,且没有static修饰,则称为内部成员类。如果类是定义在某个方法中,则称为本地类。</p>   
<p align="left">一、内部类的定义</p>   
<p align="left">class HasStatic{ //一个顶层类<br>   
&nbsp;&nbsp; static int j = 100;<br>    
}<br>    
<br>    
class Outer{&nbsp; //这是外部类<br>   
&nbsp; int CommVaule=10;<br>   
<br>   
&nbsp; class Inner extends HasStatic{ //这是一个内部成员类<br>   
&nbsp;&nbsp;&nbsp;&nbsp; static final int x = 3;&nbsp;&nbsp;&nbsp;&nbsp; //    
这是正确的,可以有静态成员常量<br>   
&nbsp;&nbsp;&nbsp; // static int y = 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    
// 错误,不能有静态成员变量<br>   
&nbsp; }<br>   
<br>   
&nbsp; static class NestedButNotInner{ //这是一个嵌入类<br>   
&nbsp;&nbsp;&nbsp; static int z = 5;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    
//正确,嵌入类可以有静态成员变量<br>   
&nbsp; }<br>   
<br>   
&nbsp; public void fun(){ //这是Outer类的一个方法<br>   
&nbsp;&nbsp;&nbsp; class localize{&nbsp;&nbsp;<br>   
&nbsp;&nbsp;&nbsp;&nbsp; //这是一个本地类,它定义在方法中,无论fun是否静态,都不能用static修饰localize<br>   
&nbsp;&nbsp;&nbsp;&nbsp; //在localize类中,除了静态成员常量之外,不允许定义任何静态成员<br>   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int k=3;<br>    
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static final int s=5;<br>    
&nbsp;&nbsp;&nbsp;&nbsp; // static int y = 4;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    
// 错误,不能有静态成员变量<br>   
&nbsp;&nbsp;&nbsp; }&nbsp;<br>   
&nbsp; }<br>   
}</p>   
<p align="left">&nbsp;&nbsp;&nbsp; 注意:内部类不能和包含它的外部类同名,也不能和其它的成员同名。和普通类一样,内部类也可以是final或abstract类型的。本地类不仅可以定义在一个方法的起始部分,它也可以像方法中的局部变量一样,定义在某个块语句中。不同方法中的本地类是可以同名的,甚至也可以和嵌入类和内部成员类同名(当然最好不要这样做)。</p>  
<p align="left">二、内部类访问外部类的成员</p>  
<p align="left">&nbsp;&nbsp;&nbsp;    
如果内部类要访问包含它的外部类的成员,有很多比较繁琐的规定,我们通过一个具体的例子来说明。我们将上面的Outer类改成这个样子:</p>   
<p align="left">class Outer{<br>    
&nbsp; int CommValue=10;<br>    
&nbsp; static int SV=100;<br>   
<br>   
&nbsp; class Inner extends HasStatic{<br>    
&nbsp;&nbsp;&nbsp; static final int x = 3;&nbsp;<br>   
&nbsp;&nbsp;&nbsp; public void call(){&nbsp; //这个方法可以直接访问外部类的任意成员<br>   
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("外部类的实例变量CommValue="+CommValue);<br>   
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("外部类的静态变量SV=&quot;+SV);<br>   
&nbsp;&nbsp;&nbsp;&nbsp; vfun();<br>   
&nbsp;&nbsp;&nbsp; }&nbsp;<br>   
&nbsp;&nbsp; /*   
内部成员类除了静态成员常量,不允许包含任何其它静态成员,定义下面这种方法是不行的:    
public static void scall(){} */<br>   
&nbsp; }<br>   
<br>   
&nbsp; static class NestedButNotInner extends HasStatic{ //记住:嵌入类是静态的<br>   
&nbsp;&nbsp;&nbsp; static int z = 5;&nbsp;<br>   
&nbsp;&nbsp;&nbsp; public void call(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    
//由于call是在嵌入类中<br>   
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("外部类的静态变SV=&quot;+SV);    
//它只能访问外部类的静态成员<br>   
&nbsp;&nbsp;&nbsp;&nbsp; //无论call是否是静态的,它都不能访问CommValue,也不能调用fun()这个实例方法<br>   
&nbsp;&nbsp;&nbsp;&nbsp; //当然,访问本类中的成员则遵守一般类的规则<br>   
&nbsp;&nbsp;&nbsp; }&nbsp;<br>   
&nbsp; }<br>   
<br>   
&nbsp; public void vfun(){<br>   
&nbsp;&nbsp;&nbsp; final int fv=3;<br>   
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fk=10;&nbsp;<br>   
&nbsp;&nbsp;&nbsp; class localize{<br>    
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void call(){<br>    
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("外部类的静态变量SV="+SV);<br>   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("外部类的实例变量CommValue="+CommValue);&nbsp;<br>   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("方法的局部常量fv="+fv);<br>   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //它不能访问fk,只能访问方法中定义的局部常量<br>   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>   
&nbsp;&nbsp;&nbsp; }<br>   
<br>   
&nbsp;&nbsp;&nbsp; System.out.println("这是外部类的成员方法");<br>   
&nbsp; }&nbsp;<br>   
<br>   
&nbsp;&nbsp; public static void sfun(){<br>   
&nbsp;&nbsp;&nbsp; final int fv=3;<br>   
&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fk=10;&nbsp;<br>   
&nbsp;&nbsp;&nbsp; class localize{&nbsp; //这个本地类可以和vfun()中的本地类同名<br>   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void call(){<br>    
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("外部类的静态变量SV="+SV);<br>   
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("外部类的实例变量CommValue="+CommValue);&nbsp;   
//错误<br>  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>  
&nbsp;&nbsp;&nbsp; }<br>   
<br>   
&nbsp;&nbsp;&nbsp; System.out.println("这是外部类的成员方法");<br>   
&nbsp; }&nbsp;<br>   
}</p>   
<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Java允许内部类中再嵌套内部类,但这样并没有太多的实际意义,而且使得程序非常难读懂,所以我们不赞成这样做。</p>  
<p align="left">现在,我们将内部类定义时所能拥有的成员归纳成下表:</p>  
<table border="1" width="80%">  
  <tr>  
    <td width="17%"> </td>  
    <td width="14%">静态常量</td>  
    <td width="14%">静态变量</td>  
    <td width="14%">实例变量</td>  
    <td width="15%">实例常量</td>  
    <td width="15%">静态方法</td>  
    <td width="15%">实例方法</td>  
  </tr>  
  <tr>  
    <td width="17%">嵌入类</td>  
    <td width="14%">√</td>  
    <td width="14%">√</td>  
    <td width="14%">√</td>  
    <td width="15%">√</td>  
    <td width="15%">√</td>  
    <td width="15%">√</td>  
  </tr>  
  <tr>  
    <td width="17%">内部成员类</td>  
    <td width="14%">√</td>  
    <td width="14%"> </td>
    <td width="14%">√</td>
    <td width="15%">√</td>
    <td width="15%"> </td>
    <td width="15%">√</td>
  </tr>
  <tr>
    <td width="17%">本地类</td>
    <td width="14%">√</td>
    <td width="14%"> </td>
    <td width="14%">√</td>
    <td width="15%">√</td>
    <td width="15%"> </td>
    <td width="15%">√</td>
  </tr>
</table>
<p align="left">下表是内部类访问外部类成员时所拥有的访问权限(由于内部类是外部类的成员,所以访问其它成员时并不受访问权限修饰符public,private,protected的限制)</p>

<table border="1" width="84%" height="174" rules=all>
  <tr>
    <td width="20%" height="16"></td>
    <td width="14%" height="16">静态常量</td>
    <td width="13%" height="16">静态变量</td>
    <td width="13%" height="16">实例变量</td>
    <td width="13%" height="16">实例常量</td>
    <td width="13%" height="16">静态方法</td>
    <td width="13%" height="16">实例方法</td>
  </tr>
  <tr>
    <td width="20%" height="33">嵌入类</td>
    <td width="14%" height="33">√</td>
    <td width="13%" height="33">√</td>
    <td width="13%" height="33">&nbsp;</td>
    <td width="13%" height="33">&nbsp;</td>
    <td width="13%" height="33">√</td>
    <td width="13%" height="33">&nbsp;</td>
  </tr>
  <tr>
    <td width="20%" height="31">内部成员类</td>
    <td width="14%" height="31">√</td>
    <td width="13%" height="31">√</td>
    <td width="13%" height="31">√</td>
    <td width="13%" height="31">√</td>
    <td width="13%" height="31">√</td>
    <td width="13%" height="31">√</td>
  </tr>
  <tr>
    <td width="20%" height="32">本地类(在实例方法中)</td>
    <td width="14%" height="32">√</td>
    <td width="13%" height="32">√</td>
    <td width="13%" height="32">√</td>
    <td width="13%" height="32">√</td>
    <td width="13%" height="32">√</td>
    <td width="13%" height="32">√</td>
  </tr>
  <tr>
    <td width="20%" height="32">本地类(在静态方法中)</td>
    <td width="14%" height="32">√</td>
    <td width="13%" height="32">√</td>
    <td width="13%" height="32">&nbsp;</td>
    <td width="13%" height="32">&nbsp;</td>
    <td width="13%" height="32">√</td>
    <td width="13%" height="32">&nbsp;</td>
  </tr>
</table>
<p align="left">另外,本地类如果要访问包含自己的方法所定义的局部量的话,只允许访问局部常量。</p>

<p align="left">三、内部类的使用</p>

<p align="left">1. 各类型的内部类之间的相互引用</p> 
 
<p align="left">我们仍然用上面的例子,不过这回简化一下:</p> 
 
<p align="left">class Outer{<br>   
<br>  
&nbsp; class Inner extends HasStatic{<br>   
&nbsp;&nbsp;&nbsp; NestedButNotInner a =new NestedButNotInner();  
//内部成员类可以使用嵌入类<br> 
&nbsp;&nbsp;&nbsp; public void call(){&nbsp;&nbsp;<br> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vfun();<br> 
&nbsp;&nbsp;&nbsp; }&nbsp;<br>  
&nbsp;&nbsp;}<br>  
<br>  
&nbsp; static class NestedButNotInner extends HasStatic{&nbsp;<br> 
//&nbsp;&nbsp;&nbsp; Inner a =new Inner();&nbsp; //错误,嵌入类不允许使用内部成员类<br> 
&nbsp;&nbsp;&nbsp;&nbsp; public void call(){&nbsp;&nbsp;}&nbsp;<br>  
&nbsp; }<br>  
<br>  
&nbsp; public void vfun(){ //这是实例方法<br> 
&nbsp;&nbsp;&nbsp;&nbsp; class localize{<br>  
&nbsp;&nbsp;&nbsp; Inner a = new Inner();&nbsp;&nbsp; //正确<br> 
&nbsp;&nbsp;&nbsp; NestedButNotInner b =new NestedButNotInner(); //&nbsp; 正确<br>  
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; public void call(){&nbsp;&nbsp;&nbsp; }<br> 
&nbsp;&nbsp;&nbsp;&nbsp; }<br> 
&nbsp;&nbsp;&nbsp; System.out.println("这是外部类的成员方法");<br> 
&nbsp; }&nbsp;<br>  
<br>  
&nbsp;public static void sfun(){ //这是静态方法<br>
&nbsp;&nbsp;&nbsp;&nbsp; class localize{<br>  
&nbsp;&nbsp; // Inner a = new Inner();&nbsp;&nbsp;  
//错误,不允许使用内部成员类<br> 
&nbsp;&nbsp;&nbsp; NestedButNotInner b =new NestedButNotInner(); //&nbsp; 正确<br>  
&nbsp;   
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; public void call(){&nbsp;&nbsp;&nbsp; }<br>  
&nbsp;&nbsp;&nbsp;&nbsp; }<br> 
&nbsp;&nbsp; class localize2{<br> 
&nbsp;&nbsp;&nbsp;&nbsp; localize a =new localize(); //正确<br> 
&nbsp;&nbsp; }<br> 
&nbsp;&nbsp; localize2 b=new localize2();&nbsp;&nbsp; //正确<br> 
&nbsp;&nbsp;&nbsp; System.out.println("这是外部类的成员方法");<br>  
&nbsp; }&nbsp;<br>  
}</p>  
  
<p align="left">&nbsp;&nbsp;&nbsp; 从上面的例子中我们可以看出,内部类之间能不能使用取决于静态还是非静态。但本地类的作用域只在包含它的方法内,外部不能访问它。</p>

<p align="left">2. 在外面访问内部类</p>

<p align="left">&nbsp;&nbsp; 
我们们再定义一个类,通过它来使用前面定义的这些内部类。该类定义如下:</p>

<p align="left">class useOuter{<br> 
&nbsp; public static void main(String argv[]){<br> 
&nbsp;&nbsp; Outer.NestedButNotInner a = new Outer.NestedButNotInner(); //嵌入类可以直接用<br>
&nbsp;&nbsp; Outer.Inner b;<br> 
&nbsp;&nbsp; Outer outObj=new Outer();<br> 
&nbsp;&nbsp; b=outObj.new Inner();&nbsp; //内部成员类必须通过外部类创建<br>
&nbsp;&nbsp; a.call();<br>
&nbsp;&nbsp; b.call();<br>
&nbsp; }<br>
}&nbsp;</p>

<p align="left">&nbsp;&nbsp; 
由于内部成员类是非静态的,必须通过外部类的实例来引用,嵌入类则不必。而对于本地类,在外部是无法看见的,只能通过调用包含它的方法来使用它。</p>

<p align="left">三、内部类的作用</p>

<p align="left">&nbsp;&nbsp;&nbsp; 首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能。<br>
<br>
&nbsp;&nbsp;&nbsp; 不过你可能要质疑,更改一下方法的不就行了吗?的确,以此作为设计内部类的理由,实在没有说服力。<br>
<br>
&nbsp;&nbsp;&nbsp; 真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题——没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。特别是在GUI程序设计时,可以通过定义多个内部类来分别继承各事件的适配器类,解决了多事件的处理问题,而不必为每个接口都写实现代码。<br>
</p>

<p align="left"><a href="index.htm">回目录</a>   <a href="java04_12.htm">上一课</a>  
<a href="java05_01.htm">下一课</a></p> 
 
</body> 
 
</html> 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -