内部类是什么,简单来说,就是定义在类内部的类(一本正经的说着废话)。

  一个正经的内部类是长这样的:

public class Outer {
class Inner{
}
}

  这是为了演示而写的类,没有什么luan用,可以看到Inner类置于Outer类的内部。

  那为什么要大费周章的在类内部定义一个类呢?不能在类外部定义类吗?内部类跟外部类有什么关系?

  确实,很多时候,在外部单独定义一个类确实更加方便,也更加通用,但内部类的存在自然有其存在的道理,内部类作为寄生在外部类的类,可以自由访问外部类的所有的属性和方法,有没有联想其我们之前说的继承,子类可以继承父类的属性和方法,但是内部类有着更高的访问权限,不仅是public属性,protected属性,就连private属性也可以轻松访问,这样就不会让修饰符限制你的想象了(手动滑稽)。

  内部类也分很多种:成员内部类、静态内部类、局部内部类、匿名内部类。今天先来说说第一种:成员内部类。

  成员内部类是最简单粗暴的内部类,上面那个栗子中的Inner类就是成员内部类,相比普通的类,成员内部类是不能有static修饰的成员或者方法的,因为成员内部类是寄生在外部类中的,所以必须先有外部类实例才能有成员内部类。在外部创建内部类对象时,姿势也不太一样,看起来像是这个样子的:

public class Test {
public static void main(String[] args) {
Outer.Inner inner = new Outer().new Inner();
}
}

  在内部类中可以访问外部类的方法和属性,外部类也可以访问内部类的方法和属性,举个栗子:

public class Outer {
private int num;
private Inner inner; Outer(){
num = 1;
inner = new Inner();
} public void print(){
System.out.println("Outer.print()");
System.out.println(inner.num);
System.out.println(num);
} class Inner{
private int num; Inner(){
num = 2;
} public void print(){
System.out.println("Inner.print()");
System.out.println(this.num);
System.out.println(Outer.this.num);
}
}
}
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
outer.print();
inner.print();
}
}

  输出如下:

Outer.print()
2
1
Inner.print()
2
1

  外部类访问内部类的姿势是先生成内部类实例,然后就能访问所有方法和属性,内部类访问外部类方法和属性则直接使用Outer.属性/方法名 即可。

  在这个栗子中,我们可以看到内部了Inner可以对外围类Outer的属性进行无限制的访问,尽管它是private修饰的。因为当我们在创建某个外围类的内部类对象时,会往内部类传入一个外部类的引用,只要我们在访问外部类的成员时,就会用这个引用来选择外围类的成员。引用内部类的时候,需要使用Outer.Inner这样的形式来声明,而不能直接使用Inner来声明(除了在Outer类中),当需要使用到内部类的时候,还是推荐使用getInnerInstance的方式来获取,特别是当内部类只有无参构造器的时候:

public class Outer {
private int num;
private Inner inner; Outer(){
num = 1;
inner = new Inner();
} public Inner getInnerInstance() {
return new Inner();
} public void print(){
System.out.println("Outer.print()");
System.out.println(inner.num);
System.out.println(num);
} public class Inner{
private int num; Inner(){
num = 2;
} public void print(){
System.out.println("Inner.print()");
System.out.println(this.num);
System.out.println(Outer.this.num);
}
}
}
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.getInnerInstance();
outer.print();
inner.print();
}
}

  这样的话,就能更好的封装了。

  当然,内部类跟外部类还有一个很重要区别:内部类可以用private修饰,而外部类是不能使用private修饰的。如果内部类仅仅在类内部使用时,使用private修饰后,就可以更好的隐藏内部信息。

  至此,内部类的第一部分讲解完毕,欢迎大家继续关注。

 

【Java入门提高篇】Day6 Java内部类——成员内部类的更多相关文章

  1. 【Java入门提高篇】Java集合类详解(一)

    今天来看看Java里的一个大家伙,那就是集合. 集合嘛,就跟它的名字那样,是一群人多势众的家伙,如果你学过高数,没错,就跟里面说的集合是一个概念,就是一堆对象的集合体.集合就是用来存放和管理其他类对象 ...

  2. 【Java入门提高篇】Day9 Java内部类——静态内部类

    今天来说说Java中的最后一种内部类--静态内部类 所谓的静态内部类,自然就是用static修饰的内部类,那用static修饰过后的内部类,跟一般的内部类相比有什么特别的地方呢? 首先,它是静态的,这 ...

  3. 【Java入门提高篇】Day21 Java容器类详解(四)ArrayList源码分析

    今天要介绍的是List接口中最常用的实现类——ArrayList,本篇的源码分析基于JDK8,如果有不一致的地方,可先切换到JDK8后再进行操作. 本篇的内容主要包括这几块: 1.源码结构介绍 2.源 ...

  4. 【Java入门提高篇】Day1 抽象类

    基础部分内容差不多讲解完了,今天开始进入Java提高篇部分,这部分内容会比之前的内容复杂很多,希望大家做好心理准备,看不懂的部分可以多看两遍,仍不理解的部分那一定是我讲的不够生动,记得留言提醒我. 好 ...

  5. 【Java入门提高篇】Day28 Java容器类详解(十)LinkedHashMap详解

    今天来介绍一下容器类中的另一个哈希表———>LinkedHashMap.这是HashMap的关门弟子,直接继承了HashMap的衣钵,所以拥有HashMap的全部特性,并青出于蓝而胜于蓝,有着一 ...

  6. 【Java入门提高篇】Day27 Java容器类详解(九)LinkedList详解

    这次介绍一下List接口的另一个践行者——LinkedList,这是一位集诸多技能于一身的List接口践行者,可谓十八般武艺,样样精通,栈.队列.双端队列.链表.双向链表都可以用它来模拟,话不多说,赶 ...

  7. 【Java入门提高篇】Day13 Java中的反射机制

    前一段时间一直忙,所以没什么时间写博客,拖了这么久,也该更新更新了.最近看到各种知识付费的推出,感觉是好事,也是坏事,好事是对知识沉淀的认可与推动,坏事是感觉很多人忙于把自己的知识变现,相对的在沉淀上 ...

  8. 【Java入门提高篇】Day16 Java异常处理(下)

    今天继续讲解java中的异常处理机制,主要介绍Exception家族的主要成员,自定义异常,以及异常处理的正确姿势. Exception家族 一图胜千言,先来看一张图. Exception这是一个父类 ...

  9. 【Java入门提高篇】Day31 Java容器类详解(十三)TreeSet详解

    上一篇很水的介绍完了TreeMap,这一篇来看看更水的TreeSet. 本文将从以下几个角度进行展开: 1.TreeSet简介和使用栗子 2.TreeSet源码分析 本篇大约需食用10分钟,各位看官请 ...

  10. 【Java入门提高篇】Day26 Java容器类详解(八)HashSet源码分析

    前面花了好几篇的篇幅把HashMap里里外外说了个遍,大家可能对于源码分析篇已经讳莫如深了.别慌别慌,这一篇来说说集合框架里最偷懒的一个家伙——HashSet,为什么说它是最偷懒的呢,先留个悬念,看完 ...

随机推荐

  1. ES6 let和const详解及使用细节

    ES6之前javascript只有全局作用域和函数作用域,所以经常会遇到变量提升了或者使用闭包的时候出错的问题. 所有a[i]都会输出10: var arr=[]; for (var i=0;i< ...

  2. continous integration environment (Jenkins and bitbucket configuration)

    ================================================================================ continous integrati ...

  3. 在你的网站实现qq登陆(php)

    这个qq的oauth2.1有个坑,坑了我半天,后来查了不少资料总算弄通了,现在把详细步骤记录下来. 步骤一.登陆http://connect.qq.com/     步骤二.创建应用.我创建的是wen ...

  4. java爬虫--jsoup简单的表单抓取案例

    分析需求: 某农产品网站的农产品价格抓取 网站链接:点击打开链接 页面展示如上: 标签展示如上: 分析发现每日价格行情包括了蔬菜,水果,肉等所有的信息,所以直接抓每日行情的内容就可以实现抓取全部数据. ...

  5. C# join子句

    join 子句可用于将来自不同源序列并且在对象模型中没有直接关系的元素相关联. 唯一的要求是每个源中的元素需要共享某个可以进行比较以判断是否相等的值. 例如,食品经销商可能拥有某种产品的供应商列表以及 ...

  6. AngularJS学习篇(三)

    创建自定义的指令 除了 AngularJS 内置的指令外,我们还可以创建自定义指令. 你可以使用 .directive 函数来添加自定义的指令. 要调用自定义指令,HTML 元素上需要添加自定义指令名 ...

  7. HTML5新特性之WebRTC[转]

    原文:http://www.cnblogs.com/jscode/p/3601648.html?comefrom=http://blogread.cn/news/ 1.概述 WebRTC是“网络实时通 ...

  8. Python爬虫入门:爬虫基础了解

    有粉丝私信我想让我出更基础一些的,我就把之前平台的copy下来了,可以粗略看一下,之后都会慢慢出. 1.什么是爬虫 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一直蜘蛛,互联网就比作一张大网,而爬虫 ...

  9. nohup和&后台运行,查看占用端口进程

    1.nohup 用途:不挂断地运行命令. 语法:nohup Command [ Arg - ] [ & ] 无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup ...

  10. 查看 docker 容器使用的资源

    在容器的使用过程中,如果能及时的掌握容器使用的系统资源,无论对开发还是运维工作都是非常有益的.幸运的是 docker 自己就提供了这样的命令:docker stats. 默认输出 docker sta ...