Java内部类超详细总结(含代码示例)
Java内部类超详细总结(含代码示例)
什么是内部类
什么是内部类?
顾名思义,就是将一个类的定义放在另一个类的内部。
概念很清楚,感觉很简单,其实关键在于这个内部类放置的位置,可以是一个类的作用域范围、一个方法的或是一个代码块的作用域范围。
所以理解了概念只是第一步,掌握细节才能彻底搞定Java的内部类特性。
看例子,这是最普通的内部类:
public class Product1 {
class Design{ private String name = "P30 pro"; public String showName() { return name; } } class Content{ private int i; Content(int value){ i = value; } int value() {return i;} } public void show(int value) { Content c = new Content(value); Design d = new Design(); System.out.println(d.showName()); System.out.println(c.value()); } public static void main(String[] args) { Product1 p = new Product1(); p.show(6000); }
}
说明:
上面这个示例展示了内部类最基础的用法,就是将一个或多个类的定义放在了外围内的内部。可以看到在show()方法中的使用和普通类一样,没有区别。
另外,在外围类的非静态方法之外的任意位置,不能通过直接new 内部类的方式创建内部类对象。会报编译错误。
像这样:
在这里插入图片描述
还有这样:
在这里插入图片描述
如果想要在外围类非静态方法之外创建内部类对象。怎么办呢?
正确的姿势是这样子:
在外围类中增加两个公共方法,返回内部类的引用。
public Design design() { return new Design(); } public Content content(int value) { return new Content(value); }
然后通过外部类对象调用方法的方式获取内部类对象。
public static void main(String[] args) { Product2 p = new Product2(); p.show(6000); Product2.Content c1 = p.content(100); Product2.Design d1 = p.design(); }
值得注意的是,外部类之外的其他类,也是不能直接访问到该外部类的内部类对象的。
会报编译错误。这也符合内部类的定义,就是为外围类服务的嘛!
内部类的特性
1.可以链接到外部类
当生成一个内部类对象时,此对象与制造它的外围对象之间就有了一种联系,所以它能访问外围对象的所有成员,而不需要任何特殊的条件。
下面的例子是《Java编程思想》中的示例
首先定义一个Selector接口
public interface Selector {
boolean end(); Object current(); void next();
}
然后定义一个Sequence类,其中定义有一个private的内部类。
public class Sequence {
private Object[] items; private int next = 0; public Sequence(int size) {items = new Object[size];} public void add(Object x) { if(next < items.length) { items[next++] = x; } } private class SequenceSelector implements Selector{ private int i = 0; public boolean end() { return i == items.length; } public Object current() { return items[i]; } public void next() { if(i < items.length) {i++;} } } public Selector selector() { return new SequenceSelector(); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for(int i = 0; i < 10; i++) { sequence.add(Integer.toString(i)); } Selector selector = sequence.selector(); while(!selector.end()) { System.out.print(selector.current() + " "); selector.next(); } }
}
说明:
可以看到SequenceSelector是一个内部类,其end()、current()和next()都用到了外围类中private的items字段。
2.使用.this和.new
.this的用法
如果需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this。
如下所示:
public class DotThis {
void name() {System.out.println("name");} public class Inner{ public DotThis outer() { return DotThis.this; } } public Inner inner() {return new Inner();} public static void main(String[] args) { DotThis dt = new DotThis(); DotThis.Inner inner = dt.inner(); inner.outer().name(); }
}
需要注意DotThis.this只是产生了正确的外部类引用。并没有创建外部类对象。
.new的用法
可以通过该语法创建内部类对象,不过要注意的是要使用外部类的对象去创建。
public class DotNew {
public class Inner{} public static void main(String[] args) { DotNew dn = new DotNew(); DotNew.Inner dnInner = dn.new Inner(); }
}
内部类分类
1、局部内部类
定义在一个方法中或是方法中某一作用域内的类。称作局部内部类。
public class Product3 {
public Section section(String inputName) { class ASection implements Section{ private String name; private ASection(String name) { this.name = name; } @Override public String hello() { return name + " say hello"; } } return new ASection(inputName); } public static void main(String[] args) { Product3 p = new Product3(); Section section = p.section("aaaaa"); System.out.println(section.hello()); }
}
ASection是一个Section接口的实现,Section接口代码如下:
public interface Section {
String hello();
}
说明:
该内部类在section()方法中,该方法之外不能访问ASection类;
方法内部类不允许使用访问权限修饰符(public、private、protected);
注意方法返回的是Section 的引用,即有向上转型。
另外还可以将内部类的定义放在方法中某一语句块中,如if语句块中。
public class Product4 {
public String check(boolean flag) { String checkId = null; if(flag) { class DetailCheck{ private String id; private DetailCheck(String id) { this.id = id; } String getId() { return id; } } DetailCheck dc = new DetailCheck("1111"); checkId = dc.getId(); } return checkId; } public static void main(String[] args) { Product4 p = new Product4(); System.out.println(p.check(true)); }
}
说明:
DetailCheck内部类在if语句块中,因此它的作用范围也在if语句块的范围之内。超出该范围是不可用的。比如这样就会编译报错:
在这里插入图片描述
2、匿名内部类
匿名内部类其实是一种特殊的方法内部类(局部内部类)。它特殊在于将内部类的定义和其对象创建结合在了一块。没有通过class关键字显示声明内部类名称,故谓之“匿名”。
看代码示例:
public class Product5 {
public Section section() { return new Section() { private String name = "hayli"; @Override public String hello() { // TODO Auto-generated method stub return name + " haha"; } }; } public static void main(String[] args) { Product5 p = new Product5(); p.section(); }
}
说明:
此处Section可以是接口,也可是基类。
3、嵌套类(静态内部类)
使用static关键字修饰的内部类,叫做静态内部类,也称作嵌套类。
嵌套类和普通内部类之间最大的区别是:
普通内部类对象隐式地保存了一个引用,指向创建它的外部类对象。而嵌套类创建对象,并不需要外部类对象。
不能从嵌套类的对象中访问非静态的外部类对象。
普通内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以包含所有这些东西。
public class Product6 {
private static int id = 100; private static class BSection implements Section{ private String name = "bbbb"; @Override public String hello() { return name + " hello"; } // 只能访问外部类的静态数据或字段 public int getId() {return id;} // 可以包含静态数据或方法 static int x = 200; public static void test1() {} // 可以再嵌套一层 static class BInner{ private String name; static void test1() {System.out.println("inner ===");} } } public static void main(String[] args) { Section section = new BSection(); section.hello(); }
总结
本篇介绍了什么是内部类、内部类最普通定义方法和Java内部类的几种具体类型详解。虽然工作中使用内部类的机会不会,但是了解这些最基础的知识,真的在项目中遇到内部类的写法,也能看懂是怎么回事了。
原文地址https://www.cnblogs.com/happyone/p/11306419.html
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java线程池的增长过程
Java线程池的增长过程通过ThreadPoolExecutor的方式创建线程池ThreadPoolExecutor 构造方法: 复制代码public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { //code... }复制代码 参数的意义: 1.corePoolSize 指定了线程池里的线程数量,核心线程池大小2.maximumPoolSize 指定了线程池里的最大线程数量3.keepAliveTime 当线程池线程数量大于corePoolSize时候,多出来的空闲线程,多长时间会被销毁。4.unit 时间单位5.workQueue 任务队列,用于存放提交但是尚未被执行的任务。6.threadFactory 线程工厂,用于创建线程,一般可...
- 下一篇
利用Idea重构功能及Java8语法特性——优化深层嵌套代码
利用Idea重构功能及Java8语法特性——优化深层嵌套代码当遇到深层嵌套代码,如for,if,lambda表达式或内部类及这些代码的组合,这时我们可以通过Java 8的语法特性来进行优化。 下面的代码是一个嵌套循环的示例。 复制代码public MappedField getMappedField(final String storedName) { for (final MappedField mf : persistenceFields) { for (final String n : mf.getLoadNames()) { if (storedName.equals(n)) { return mf; } } } return null; }复制代码重构1:嵌套的for/if语句通畅可以通过Java 8中的stream来替代。 Optional found = persistenceFields.stream().flatMap(mappedField -> mappedField.getLoadNames().stream()).filter(storedName::e...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- 2048小游戏-低调大师作品
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS关闭SELinux安全模块
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- 设置Eclipse缩进为4个空格,增强代码规范
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作