/*    innerClass
        从实际的开发来看,真正写到内部类的时候是在很久以后了,短期内如果是自己编写代码,几乎是见不到内部类出现的
        讲解它的目的第一个是为了解释概念,另外一个就是也是为后期的一些复杂程序做铺垫
        
        所谓的内部类指的是在一个类的内部(外部类)定义类结构的一种处理形式

*/

/*    内部类的基本概念
        类的组成永远都是只有两点:成员(Field),方法(Method),但是几乎所有的程序里面斗不会对嵌套的结构有任何的限定
        所以内部类指的是在一个类的内部可以继续嵌套其他类结构的一种形式代码
        并且从理论上来讲可以一直嵌套下去
        下面首先来看一下内部类的基本形式
        范例:观察内部类代码

    class Outer{  // 外部类
private String info = "Hello World!":
class lnner{ // 内部类
public void print(){
System,out.println(Outer.this.info): // 输出info 属性内容
}
}
public void fun(){
lnner in = new lnner(): //实例化内部类对象
in.print(): // 调用内部类的方法
}
}
public class innerClass{
public static void main(String args[]){
Outer out = new Outer():
out.fun():
}
}
// 结果 Hello World!

类本身的核心组成就应该是属性和方法,但是如果引用了内部类,就相当于破坏了这样的程序结构
            所以内部类所带来的最为严重的问题就在于程序结构的破坏,但是破坏了那么也应该有一些收益
             那么内部类的好处在哪里呢?为了观察出内部类的好处,那么下面将内部类拿出来,变为两个类
        范例:内部类拿出来

    class Outer{  // 外部类
private String info = "Hello World!": public void fun(){
// 将当前对象传递到内部类之中
lnner in = new lnner(this): //实例化内部类对象
in.print(): // 调用内部类的方法
}
// 为in定义一个getter方法
public String getlnfo(){
return info:
}
}
class lnner{ // 内部类
private Outer temp: // 此处应该接收外部类实例化好的Outer类对象
public lnner(Outer temp){
this.temp = temp:
}
public void print(){
// 此处需要访问外部类中的私有属性,所以不能够直接输出属性,需要Outer类提供有getter
// 方法应该由对象进行调用,所以现在需要有一个实例化对象
// 相当于就是外部的out。getlnfo()
System,out.println(this.temp.getlnfo()): // 输出info 属性内容
}
}
public class innerClass{
public static void main(String args[]){
Outer out = new Outer():
out.fun():
}
}
// 结果 Hello World!

代码修改完成之后实际上就可以感受到内部类的最大好处是可以直接进行外部类中私有属性的直接访问
            那么清楚内部类的基本定义之后,实际上现在又会存在有一下几个问题:
                1.在编写代码一直强调:只要是属性的访问,一定要加上“this ”,这个时候由于属性是外部类中的
                所以要想操作this 那么就必须使用“外部类.this.属性”  ( 上面: Outer.this.info)
                
                如果内部类中的方法直接采用了“this.属于”表示的是什么,只是本类(内部类)中的属性
                
                2.以上的代码发现内部类可以方便访问外部类中的私有属性,同时发现外部类中的fun()方法里面也占着内部类的对象
                那么内部类的私有属性外部类也可以直接利用对象访问

    class Outer{  // 外部类
private String info = "Hello World!":
class lnner{ // 内部类
private String msg = "+++++++++":// 内部类的私有属性
public void print(){
System,out.println(Outer.this.info): // 输出info 属性内容
}
}
public void fun(){
lnner in = new lnner(): //实例化内部类对象
in.print(): // 调用内部类的方法
System.out.println(in.msg):// 内部类对象直接调用属性
}
}
public class innerClass{
public static void main(String args[]){
Outer out = new Outer():
out.fun():
}
}
/*
结果
Hello World!
++++++++++++
*/

内部类与外部类之间的私有属性都是可以直接进行访问的,这一点要比分为两个类更加的方便
                
                3.现在发现实例化内部类的对象操作都是在外部类中的fun()方法里面完成的
                那么如果现在不希望通过外部类的方法操作内部类,那么也可以根据一下的语法,直接在其他类实例化内部类对象
                语法结构:
                    外部类名称.内部类名称 对象名称 = new 外部类().内部类()
                    内部类的标准的名称应该是“外部类.内部类”,只不过“.”不可能直接出现在文件中
                    所以java 将其进行了转换,在文件名称中使用“$”来代替“.”

    class Outer{  // 外部类
private String info = "Hello World!":
class lnner{ // 内部类
public void print(){
System,out.println(Outer.this.info): // 输出info 属性内容
}
}
}
public class innerClass{
public static void main(String args[]){
Outer.lnner in = new Outer().new lnner():
in.print():
}
}
// 结果 Hello World!

4.内部类中可以利用private定义私有内部类:

    class Outer{  // 外部类
private String info = "Hello World!":
private class lnner{ // 内部类
public void print(){
System,out.println(Outer.this.info): // 输出info 属性内容
}
}
}
public class innerClass{
public static void main(String args[]){
Outer.lnner in = new Outer().new lnner():
in.print():
}
}
// 结果: 出错

对于内部类的概念与它的结构有个先期的认识即可
                
*/

/*    内部类定义深入
        在之前使用的都是普通类的形式进行了内部类的定义,实际上在内部结构上也可以应用在抽象类和接口上
        
        范例:在抽象类上定义内部类

    abstract class AbstractOuter{ // 抽象类的外部类
public abstract void peintOuter();
abstract class AbstractInner{ // 抽象内部类
public abstract void printInner();
}
class Inner{ // 普通的内部类
public void print(){
System.out.println("加油!");
}
}
}
class OuterImpl extends AbstractOuter{ // 继承了外部抽象类
public void peintOuter(){
new Inner().print(); // 实例化内部类的对象调用方法
}
}
public class innerClass{
public static void main(String args[]){
AbstractOuter out = new OuterImpl();
out.peintOuter();
}
}

在定义内部抽象类的时候是不会影响到子类的,也就是说子类只需要覆写它所继承的抽象类中的抽象方法即可
            
        范例:定义内部抽象类的子类

abstract class AbstractOuter{ // 抽象类的外部类
public abstract void peintOuter();
abstract class AbstractInner{ // 抽象内部类
public abstract void printInner();
}
class Inner{ // 普通的内部类
public void print(){
System.out.println("加油!");
}
}
}
class OuterImpl extends AbstractOuter{ // 继承了外部抽象类
public void peintOuter(){
new Inner().print(); // 实例化内部类的对象调用方法
}
class InnerImpl extends AbstractInner{ // 内部抽象类
public void printInner(){
new Inner().print();
}
}
}
public class innerClass{
public static void main(String args[]){
AbstractOuter.AbstractInner in = new OuterImpl(),new InnerImpl();
in.peintOuter();
}
}

除了内部抽象类之外也可以实现内部的接口定义
            
        范例:定义内部接口

interface IOuter{
public void peintOuter();
interface IInner{
public void printInner();
}
class B{
public void print(){
System.out.println("++++++++");
}
}
}
class OuterImpl implements IOuter{
public void peintOuter(){
class InnerImpl implements IInner{
public void printInner(){
new B().print();
}
}
}
}
public class innerClass{
public static void main(String args[]){
IOuter.IInner in = new OuterImpl().new InnerImpl();
in.printInner();
}
}

内部类完整的打破了程序结构定义要求,也就是说程序里面没有对内部类的结构做出任何的限制,只要该定义符合语法要求即可使用

*/

/*    利用static定义内部类
        利用static定义的属性或者是方法,是不受到类的控制的,也就是说相当于是一个局外的结构
        所以如果内部类上用了static定义,那么就表示此内部类变为了一个外部类,但是需要注意的是,如果它使用了static定义,那么只能够访问外部类中的static属性
        范例:利用static定义内部类

    class Outer{  // 外部类
private static String info = "Hello World!":
static class lnner{ // 内部类
public void print(){
System.out.println(info): // 输出info 属性内容
}
}
}
public class innerClass{
public static void main(String args[]){ }
}

那么既然现在static的内部类变为了外部类,外部类就可以被其他类直接进行操作
            但是这个时候的实例化对象格式:
                外部类名称.内部类名称 对象名称 = new 外部类.内部类():
            加上了static之后,那么实际上也就表示这个内部类的名字就成了“外部类.内部类”
        范例:实例化内部类对象

class Outer{  // 外部类
private static String info = "Hello World!":
static class lnner{ // 内部类
public void print(){
System.out.println(info): // 输出info 属性内容
}
}
}
public class innerClass{
public static void main(String args[]){
Outer.lnner oi = new Outer.lnner():
oi.print():
}
}
// 结果 Hello World!

以后见到程序类库中出现有“Xxxx.Xxxx”就表示内部类
            
        对于 static 定义内部类的形式在实际开发之中使用很多,但是也可以在接口上使用,即:接口内部可以使用 static 定义外部接口
            
        范例:

interface IOuter{
static interface IInner{ // 静态的内部接口
public void print();
}
}
class InnerImpl implements IOuter.IInner{
public void print(){
System.ou.println("+++++++++");
}
}
public class innerClass{
public static void main(String args[]){
IOuter.IInner oi = new InnerImpl():
oi.print():
}
}

*/

/*    方法中定义内部类
        理论上内部类可以在任何的位置上定义,包括:代码块中,类中,方法中。所以在实际的开发之中,有可能直接在方法里使用内部类
        范例:观察方法中定义内部类

class Outer{  // 外部类
private String info = "Hello World!":
public void dun(int temp){ // 方法中的参数
double sal = 9000.0: // 方法中定义的普通变量
class lnner{ // 内部类,方法中定义
public void print(){
System.out.println("Outer类中的info属性= "+Outer.this.info):
System.out.println("fun()方法中的参数,temp = "+temp):
System.out.println("fun()方法定义的临时变量,sal ="+sal):
}
}
new lnner().print():// 实例化内部类对象,调用方法输出
}
}
public class innerClass{
public static void main(String args[]){
Outer out = new Outer():// 实例化Outer类对象
out.fun(100):
}
}
/*
结果
Outer类中的info属性= Hello World!
fun()方法中的参数,temp = 100
fun()方法定义的临时变量,sal = 9000.0
*/

注意:现在使用的是JDK1.8版本
                那么这个版本的好处是避免了一些复杂的细节,之所以会避免是为了整体的设计考虑的,而以上的代码,在JDK1.7时就会出现问题
                因为在JDK1.7以前有一个约定,如果一个方法中定义了内部类,那么这个内部类要想访问方法的参数或者是定义的变量,则参数或者是变量前必须加上final
                之所以可以不加final了,主要是因为那个Lamde与方法引用一起出现所造成的新局面
*/

/*    anonymousInternal 匿名内部类
        匿名内部类的使用
        
    内容
        匿名内部类 = 没有名字的内部类
        任何的技术出现都有它可以解决的问题,所以下面首先来分析一下没有匿名内部类的情况
        范例:观察程序代码的问题

interface A{// 定义了一个接口
public void ptintA();
}
class X implements A{
public void ptintA(){
System.out.println("AAAAAAAAAAAAAAA");
}
}
publlic class anonymousInternal{
publlic static void main(String args[]){
A a = new X();
a.ptintA();
}
}

有了一个接口,而后为接口定义了一个子类,在主类中利用对象的向上转型进行对象实例化操作
        但是现在有一个问题出现了,本程序中为接口A定义了一个子类X,但是假设说此时的这个X子类只使用唯一的一次
        那么有必要将其定义成一个单独的类吗?那么此时的设计就有些夸张了。
        那么就可以利用匿名内部类的概念来解决,而且匿名内部类必须以抽象类或接口为前提进行使用
        范例;使用匿名内部类

interface A{// 定义了一个接口
public void ptintA();
}
public class anonymousInternal{
public static void main(String args[]){
A a = new A(){ // 匿名内部类
public void ptintA(){
System.out.println("***********************");
}
}
a.ptintA();
}
}           

现在的基本感觉此语法很槽糕,程序的结构很混乱
                    
        范例:

abstract class AbstractA{
private String mdg = "+++++++++++++";
public String getMsg(){
return this.msg;
}public abstract void print();
}
public class anonymousInternal{
public static void main(String args[]){
AbstractA a = new AbstractA(){ // 匿名内部类
public void ptint(){
System.out.println(this.getMsg());
}
}
a.ptintA();
}
}

匿名内部类的最大特点是可以减少类的定义个数,所以在以后的开发之中会大量的使用匿名内部类来进行某些接口子类的定义
            这一点在后面讲解的多线程开发之中非常有用处,同时匿名内部类也是 Lembda 表达式的原始雏形         
    
    总结
        可以看懂匿名内部类就够了,其他的慢慢随着代码的编写经验的增长自然就会了

*/

/*    总结
        1.不要去考虑怎么用,一般的开发很少会用到,但是会使用
        2.内部类先看明白它的语法形式

*/

菜鸡的Java笔记 第二十六 - java 内部类的更多相关文章

  1. 菜鸡的Java笔记 第二十八 - java 包的定义

    包的主要作用以及定义    包的导入操作    系统常见的开发包    jar 程序命令        包的定义        在任何的操作系统之中都有一个统一的共识:同一个目录下不能够存在有相同的文 ...

  2. 菜鸡的Java笔记 第十六 - java 引用传递

    referenceDelivery    引用传递是整个java 的精髓,也是所有初学者最难学的地方        引用的本质:同一块堆内存可以被不同的栈内存所指向    下面通过三道程序来进行引用传 ...

  3. 菜鸡的Java笔记 第二十四 - java 接口的基本定义

    1.接口的基本定义以及使用形式        2.与接口有关的设计模式的初步认识        3.接口与抽象类的区别                 接口与抽象类相比,接口的使用几率是最高的,所有的 ...

  4. 菜鸡的Java笔记 第二十二 - java 对象多态性

    本次只是围绕着多态性的概念来进行讲解,但是所讲解的代码与实际的开发几乎没有关系,而且多态一定是在继承性的基础上才可以操作的,        而本次将使用类继承的关系来描述多态的性质,实际的开发中不会出 ...

  5. 菜鸡的Java笔记 第二十九 - java 单例设计模式

    SingleCase 单例设计模式        1.单例设计模式的特点        2.多例设计模式的特点    内容    单例设计模式        现在如果说有这么一个程序类 class S ...

  6. “全栈2019”Java多线程第二十六章:同步方法生产者与消费者线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  7. 菜鸡的Java笔记 第二十五 wrapperClass 包装类

    wrapperClass 包装类         1.包装类的特点        2.装箱与拆箱操作        3.数据转型处理            内容        Object 类可以接收 ...

  8. 菜鸡的Java笔记 第二十 - java 方法的覆写

    1.方法的覆写    当子类定义了与父类中的完全一样的方法时(方法名称,参数类型以及个数,返回值类型)这样的操作就称为方法的覆写    范例:观察方法的覆写 class A{ public void ...

  9. 菜鸡的Java笔记 第十九 - java 继承

    继承性的主要目的,继承的实现,继承的限制                继承是面向对象中的第二大主要特点,其核心的本质在于:可以将父类的功能一直沿用下去                为什么需要继承? ...

随机推荐

  1. Java并发编程实战——读后感

    未完待续. 阅读帮助 本文运用<如何阅读一本书>的学习方法进行学习. P15 表示对于书的第15页. Java并发编程实战简称为并发书或者该书之类的. 熟能生巧,不断地去理解,就像欣赏一部 ...

  2. 阿里 Midway 正式发布 Serverless v1.0,研发提效 50%

    Github:https://github.com/midwayjs/midway 开源为了前端和 Node.js 的发展,点 Star! 去年阿里提出 Serverless 架构,并利用其新一代研发 ...

  3. 字符串编码js第三方类库text-encoding

    GITHUB地址:https://github.com/BCode001/text-encoding

  4. 从0到1使用Kubernetes系列(二):安装工具介绍

    该系列第一篇为:<从0到1使用Kubernetes系列--Kubernetes入门>.本文是Kubernetes系列的第二篇,将介绍使用Kubeadm+Ansible搭建Kubernete ...

  5. NX开发 刀路生成

    此段是可以生成程序的完整代码,只有从坐标(10,10,10)到(500,500,500)一根刀轨.motion_ptr->feed_value 的值为0时生成G00,非0时生成G01.此代码只有 ...

  6. 1.2 Simple Code!(翻译)

    Simple Code! 简洁编码 Playing football is very simple, but playing simple football is the hardest thing ...

  7. 初始CSS01

    CSS基础知识 CSS介绍 CSS全称为层叠样式表,与HTML相辅相成,实现网页的排版布局与样式美化. 使用方式 根据样式表在页面中呈现的方式不同,可以通过以下三种方式在页面中使用格式 内联样式 改样 ...

  8. AgileConfig 轻量级配置中心 1.5 发布 - 支持多环境配置

    AgileConfig 从发布到现在,收到不同学的 issue 说需要多环境的支持.也就是一个应用在不同的环境下可以配置不同的配置项.这是一个非常有用的功能,就跟我们开发的时候会设置多个 appset ...

  9. Mac上安装Grafana

    Mac上安装Grafana 一.背景 二.安装步骤 1.通过 Home Brew 安装 2.通过二进制包进行安装 1.下载 2.grafana配置文件的路径 3.修改grafana配置 1.修改默认的 ...

  10. 安装pytorch的细节记录

    1.根据教程安装pytorch的时候发现太慢了,无法容忍,根据https://blog.csdn.net/zzq060143/article/details/88042075z在Ancona Prom ...