Java核心类库——内部类那点事儿
内部类 ———定义在类的内部的类
为什么需要内部类?
典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。
java中的内部类和接口加在一起,可以实现多继承。
可以使某些编码根简洁。
隐藏你不想让别人知道的操作。
使用内部类最吸引人的原因是:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。
特点:
一、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号。
二、内部类可以直接或利用引用访问外部类的属性和方法,包括私有属性和方法(但静态内部类不能访问外部类的非静态成员变量和方法)。内部类所访问的外部属性的值由构造时的外部类对象决定。
三、而外部类要访问内部类的成员,则只能通过引用的方式进行,可问内部类所有成员
四、访问机制:
System.out.println(this.x);或System.out.println(x);//内部类访问内部类的成员变量或成员方法可用此方法。
System.out.println(OuterClass.this.x);//内部类访问外部类的同名变量时可用此方法,如果没有同名可用System.out.println(x);
五、内部类可以使用任意的范围限定:public/private/protected class InnerClass,且严格按照这几种访问权限来控制内部类能使用的范围。普通类的范围限定只可以是public或者不加。
六、内部类的命名不允许与外部类 重名,内部类可以继承同级的内部类,也可继承其它类(除内部类和外部类)。
七、内部类可以定义为接口,并且可以定义另外一个类来实现它
八、内部类可以定义为抽象类,可以定义另外一个内部类继承它
九、内部类使用static修饰,自动升级为顶级类,外部类不可以用static修饰,用OuterClass.InnerClass inner=new OuterClass.InnerClass();创建实例。内部类还可定义为final.
十、内部类可以再定义内部类(基本不用)
十一、方法内的内部类:
方法内的内部类不能加范围限定(protected public private)
方法内的内部类不能加static修饰符
方法内的内部类只能在方法内构建其实例
方法内的内部类如果访问方法局部变量,则此局部变量必须使用final修饰
1)静态内部类(静态嵌套类)
从技术上讲,静态嵌套类不属于内部类。因为内部类与外部类共享一种特殊关系,更确切地说是对实例的共享关系。而静态嵌套类则没有上述关系。它只是位置在另一个类的内部,因此也被称为顶级嵌套类。
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类不能访问外部类的成员和方法。
语法
1 package com.tarena.day13; 2 3 import com.tarena.day13.Foo.Koo; 4 /** 5 * 静态类内部语法演示 6 */ 7 public class StaticInner { 8 public static void main(String[] args) { 9 Koo koo = new Koo(); 10 System.out.println(koo.add());//4 11 } 12 13 } 14 class Foo{ 15 int a = 1; 16 static int b = 3; 17 /** 静态内部类,作用域类似于静态变量,属于类的 */ 18 static class Koo{ 19 public int add(){ 20 //a ,不能访问a 21 return b+1; 22 } 23 } 24 }
2)成员内部类
* 1 成员内部类必须利用外部类实例创建
* 2 成员内部类可以共享外部类的实例变量
1 import com.tarena.day13.inn.Goo.Moo; 2 3 public class InnerClassDemo { 4 public static void main(String[] args) { 5 //Moo moo = new Moo(); //编译错误,必须创建Goo的实例 6 Goo goo = new Goo(); 7 Moo moo = goo.new Moo();//利用goo实例创建Moo实例 8 Moo moo1 = goo.new Moo(); 9 //moo和moo1共享同一个goo实例的实例变量 10 System.out.println(moo.add());//2 11 System.out.println(moo1.add());//2 12 Goo goo1 = new Goo(); 13 goo1.a = 8; 14 Moo m1 = goo1.new Moo(); 15 Moo m2 = goo1.new Moo(); 16 System.out.println(m1.add());//9 17 System.out.println(m2.add());//9 18 19 } 20 } 21 class Goo{ 22 int a = 1; 23 /**成员内部类*/ 24 class Moo{ 25 public int add(){ 26 return a+1; 27 } 28 } 29 }
3)局部内部类(方法内部类)
(1)、方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
(2)、方法内部类对象不能使用该内部类所在方法的非final局部变量。
因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。用法
1 package com.tarena.day13.inn; 2 3 import java.util.Comparator; 4 5 /** 6 * 局部内部类 7 */ 8 public class LocalInnerClassDemo { 9 public static void main(String[] args) { 10 int a = 5; 11 final int b = 5; 12 //局部内部类,定义在方法内部,作用域类似于局部变量 13 //仅仅在方法内部可见 14 //在局部内部类中可以访问方法中的局部final变量 15 class Foo{ 16 public int add(){ 17 return b;//正确 18 //return a;//编译错误 19 } 20 } 21 22 Foo foo = new Foo(); 23 //临时的自定义比较规则 24 class ByLength implements Comparator<String>{ 25 public int compare(String o1,String o2){ 26 return o1.length()-o2.length(); 27 } 28 } 29 } 30 31 }
4)匿名内部类
顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。
匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:
·类在定义后马上用到。
·类非常小(SUN推荐是在4行代码以下)
·给类命名并不会导致你的代码更容易被理解
在使用匿名内部类时,要记住以下几个原则:
·匿名内部类不能有构造方法。
·匿名内部类不能定义任何静态成员、方法和类。
·匿名内部类不能是public,protected,private,static。
·只能创建匿名内部类的一个实例。
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
A、继承式的匿名内部类和接口式的匿名内部类。
1 import java.util.Arrays; 2 import java.util.Comparator; 3 4 /**匿名内部类 语法*/ 5 public class AnnInnerClass { 6 7 public static void main(String[] args) { 8 // TODO Auto-generated method stub 9 Yoo yoo = new Yoo();//创建Yoo的实例 10 Yoo y1 = new Yoo(){}; 11 //new Yoo(){}创建匿名类实例 12 //匿名类new Yoo(){}是继承Yoo类,并且同时创建了对象 13 //new Yoo(){}是Yoo的子类型,其中{}是类体(class Body) 14 //类体中可以定义任何类内的语法,如:属性,方法,方法重载,方法覆盖,等 15 //子类型没有名字,所以叫匿名类! 16 Yoo y2 = new Yoo(){ 17 public String toString(){//方法重写(覆盖) 18 return "y2"; //y2是子类的实例 19 } 20 }; 21 System.out.println(y2);//"y2",调用了匿名类对象toString() 22 //匿名内部类可以继承/实现 于 类,抽象类,接口等 23 //按照继承的语法,子类型必须实现所有的抽象方法 24 25 //Xoo x = new Xoo(){};//编译错误,没有实现方法 26 final int b = 5; 27 Xoo xoo = new Xoo(){ //是实现接口,并且创建匿名类实例,不是创建接口对象 28 public int add(int a){//实现接口中的抽象方法 29 return a+b; //要访问局部变量b,只能访问final变量 30 } 31 }; 32 System.out.println(xoo.add(5));//10,调用对象的方法 33 //Comparator接口也可以使用匿名类的方式 34 Comparator<String> byLength = new Comparator<String>(){ 35 public int compare(String o1,String o2){ 36 return o1.length()-o2.length(); 37 38 } 39 }; 40 String[] names = {"Andy","Tom","Jerry"}; 41 Arrays.sort(names,byLength); 42 System.out.println(Arrays.toString(names)); 43 //也可以这样写,工作中常用 44 Arrays.sort(names,new Comparator<String>(){ 45 public int compare(String o1,String o2){ 46 return o1.length()-o2.length(); 47 } 48 }); 49 } 50 51 }
接口式的匿名内部类是实现了一个接口的匿名类。而且只能实现一个接口。
B。参数式的匿名内部类。
1 class Bar{ 2 void doStuff(Foo f){ 3 } 4 } 5 interface Foo{ 6 void foo(); 7 } 8 class Test{ 9 static void go(){ 10 Bar b = new Bar(); 11 b.doStuff(new Foo(){ 12 public void foo(){ 13 System.out.println("foofy"); 14 } 15 }); 16 } 17 }
构造内部类对象的方法有:
1、内部类在自己所处的外部类的静态方法内构建对象或在另一个类里构造对象时应用如下形式:
(1)OuterClass out = new OuterClass();
OuterClass.InnerClass in = out.new InnerClass();
(2)OuterClass.InnerClass in=new OuterClass().new InnerClass();
其中OuterClass是外部类,InnerClass是内部类。
2、内部类在它所在的外部类的非静态方法里或定义为外部类的成员变量时,则可用以下方式来构造对象:
InnerClass in = new InnerClass();
3、如果内部类为静态类,则可用如下形式来构造函数:
OuterClass.InnerClass in = new OuterClass.InnerClass();
无需再利用外部类的对象来来构造内部类对象,如果静态内部类需要在静态方法或其它类中构造对象就必须用上面的方式来初始化。
转载于:https://www.cnblogs.com/hqr9313/archive/2012/04/16/2452906.html
Java核心类库——内部类那点事儿相关推荐
- Java核心类库篇8——网络编程
Java核心类库篇8--网络编程 1.七层网络模型 OSI(Open System Interconnect),即开放式系统互联,是ISO(国际标准化组织)组织在1985 年研究的网络互连模型. 当发 ...
- Java核心类库篇7——多线程
Java核心类库篇7--多线程 1.程序.进程和线程 程序 - 数据结构 + 算法,主要指存放在硬盘上的可执行文件 进程 - 主要指运行在内存中的可执行文件 线程就是进程内部的程序流 操作系统内部支持 ...
- Java核心类库篇6——IO
Java核心类库篇6--IO 1.File 1.1.构造方法 方法声明 功能介绍 public File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 ...
- Java核心类库篇5——异常
Java核心类库篇5--异常 java.lang.Throwable类是Java语言中错误(Error)和异常(Exception)的超类 其中Error类主要用于描述Java虚拟机无法解决的严重错误 ...
- Java核心类库篇4——集合
Java核心类库篇4--集合 1.集合的意义 记录单个数据内容时,则声明一个变量 记录多个类型相同的数据内容时,声明一个一维数组 记录多个类型不同的数据内容时,则创建一个对象 记录多个类型相同的对象数 ...
- Java核心类库篇3——util
Java核心类库篇3--util 1.Date 用于描述特定的瞬间,也就是年月日时分秒,可以精确到毫秒 1.1.构造方法 方法声明 功能介绍 public Date() 获取当前时间表示的date对象 ...
- Java核心类库篇2——lang
Java核心类库篇2--lang 1.Object 该类是所有类的父类,每个类都使用它作为超类,没有任何属性 方法声明 功能介绍 Object() 使用无参方式构造对象 boolean equals( ...
- Java核心类库篇1——简介
Java核心类库篇1--简介 1.核心类库 包名 主要功能 java.applet 提供了创建applet需要的所有类 java.awt.* 提供了创建用户界面以及绘制和管理图形.图像的类 java. ...
- jre包括jvm和java核心类库_包含JVM标准实现及Java核心类库
包含JVM标准实现及Java核心类库 点击次数:1533 更新日期:2013-03-24 "青花瓷Java版"为北京师范大学教育学部蔡苏作词原创,覆盖教育技术学院专业选修课< ...
最新文章
- Maven 手动添加 JAR 包到本地仓库
- 2022-2028年中国羧基丁腈胶乳行业市场发展调研及投资前景分析报告
- 【JUC并发编程13】异步回调
- SAP Spartacus B2B ListComponent响应回车事件的实现
- Windows下,Netbeans使用C++的配置方法
- 常量 数组 函数 枚举 结构体与指针
- qmenubar 添加按钮_QMenuBar,QMenu和QAction(QMenuBar, QMenu QAction)
- 跨域请求/SpringMVC拦截器
- sql server运算符_了解SQL Server中集合理论与集合运算符之间的相互作用
- linux的so命令,每天一个 Linux 命令(67): ldd 命令
- 探寻C++最快的读取文件的方案
- java开发英语词典app_英语词典app哪个好 5款好用的英语词典app推荐
- 数据库与REDIS缓存数据一致性解决方案
- Telegram Download Default Chat Wallpaper
- 03:成绩排序 个人博客:doubleq.win
- 流式低代码编程,拖拽节点画流程图并运行
- Spring源代码分析(11)---JDBC Dao(老树发新芽)
- HTTP协议实现文件下载
- 画论24 郭若虛《图画见闻志》
- 关于Springboot定时任务
热门文章
- mysql pre_commit_Git — Pre-commit钩子的使用
- 一千万条数据去重_simhash算法:海量千万级的数据去重
- python基于svm的异常检测_[scikit learn]:异常检测-OneClassSVM的替代方案
- 【clickhouse】clickhouse TCP 方式发送数据 ClickHouse-Native-JDBC
- 【ElasticSearch】Es 缓存
- 【lucene】lucene自定义评分
- 【MySQL】sql语句中exists和in有何区别?
- Spark报错: Invalid Spark URL: spark://YarnScheduler@stream_test_nb:40659
- SparkStreaming之updateStateByKey
- Spring : @EnableConfigurationProperties注解