java学习笔记系列:

java学习笔记8--接口总结

java学习笔记7--抽象类与抽象方法

java学习笔记6--类的继承、Object类

java学习笔记5--类的方法

java学习笔记4--对象的初始化与回收

java学习笔记3--类与对象的基础

java学习笔记2--数据类型、数组

java学习笔记1--开发环境平台总结

本文地址:http://www.cnblogs.com/archimedes/p/java-study-note9.html,转载请注明源地址。

java内部类分为: 非静态内部类、静态内部类、局部内部类、匿名内部类

内部类的共性:

(1)内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。

(2)内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的 。

(3)内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。

java 中的内部类和接口加在一起,可以的解决常被 C++ 程序员抱怨 java 中存在的一个问题:没有多继承。实际上,C++ 的多继承设计起来很复杂,而 java 通过内部类加上接口,可以很好的实现多继承的效果。

非静态内部类

当一个类作为另一个类的非静态成员,则这个类就是一个非静态内部类。

创建非静态内部类是很容易的,只需要定义一个类让该类作为其他类的非静态成员。该非静态内部类和成员变量或者成员方法没有区别,同样可以在非静态内部类前面加可以修饰成员的修饰符。创建非静态内部类的基本语法如下所示:

class OutClass {class InClass {//内部类成员
    }//外部类成员
}

在内部类的程序中,是经常会进行外部类和内部类之间访问的。在外部类中访问内部类是很容易的,只要把内部类看成一个类,然后创建该类的对象,使用对象来调用内部类中的成员就可以了。

在外部类中访问内部类的程序--举个例子:

class OutClass {class InClass {    //创建非静态内部类int i = 5;    //内部类成员
    }public void fun() {    //外部类成员InClass in = new InClass();    //创建一个内部类对象int i = in.i;        //访问内部类成员System.out.println("InClass's var is: " + i);}
}
public class javatest {  public static void main(String args[ ]) { OutClass out = new OutClass();out.fun();}
}

运行结果:

InClass's var is: 5

分析:在main方法中,首先创建一个外部类对象,然后访问外部类的成员方法。在外部类的成员方法中,创建了一个内部类对象,然后使用内部类对象调用内部类的成员变量,从而得到结果。编译该程序将产生三个class文件,分别是主类、外部类和内部类。内部类产生的class文件的名称为OutClass$InClass.class,在该名称中可以区分该内部类到底是哪一个类的内部类。

不但可以在外部类中访问内部类,还可以在外部类外访问内部类。在外部类外访问内部类的基本语法如下所示。

OutClass.InClass oi=new OutClass().new InClass();

使用该方法就能够创建一个内部类对象,使用该内部类对象就可以访问内部类的成员。该方法是不容易理解的,可以分为下面的两条语句:

Wai w=new Wai();

Wai.Nei wn=w.new Nei();

这样就很容易理解了。首先是创建一个外部类的对象,然后让该外部类对象调用创建一个内部类对象。

在外部类外访问内部类的程序--举个例子:

class OutClass {class InClass {    //创建非静态内部类int i = 5;    //内部类成员int j = 6;}
}
public class javatest {  public static void main(String args[ ]) { OutClass.InClass oi1 = new OutClass().new InClass();OutClass ocClass = new OutClass();OutClass.InClass oi2 = ocClass.new InClass();System.out.println("InClass's var i is: " + oi1.i);System.out.println("InClass's var j is: " + oi1.j);  }
}

在示例代码中使用了两种方法来从外部类外访问内部类。在外部类外访问内部类时,是不能够直接创建内部类对象的,因为内部类只是外部类的一个成员。所以要想创建内部类对象,首先要创建外部类对象,然后以外部类对象为标识来创建内部类对象。

在内部类中访问外部类

在内部类中访问外部类,就像所有的同一个类中成员互相访问一样,这样是没有限制的,包括将成员声明为private私有的。

举个例子:

class OutClass {int i = 8;    //外部类成员变量class InClass {    //创建非静态内部类public void fun() {System.out.println("OutClass's var is: " + i);}}
}
public class javatest {  public static void main(String args[ ]) { OutClass oc = new OutClass();    //创建外部类对象OutClass.InClass oi = oc.new InClass();    //创建内部类对象oi.fun();    //调用内部类中的成员
   }
}

在示例代码中,在内部类中定义了一个fun来访问外部类中的成员变量i。可以看到从内部类中访问外部类是非常容易的,不需要添加任何内容,就像成员方法间调用一样。如果外部类中也有一个成员变量i,得到的是内部类成员变量的值。下面通过示例代码解决这个问题:

class OutClass {int i = 8;    //外部类成员变量class InClass {    //创建非静态内部类int i = 9;OutClass oc = new OutClass();public void fun() {    //内部类成员System.out.println("InClass's var is: " + i);System.out.println("OutClass's var is: " + oc.i);}}
}
public class javatest {  public static void main(String args[ ]) { OutClass oc = new OutClass();    //创建外部类对象OutClass.InClass ic = oc.new InClass();    //创建内部类对象ic.fun();    //调用内部类中的成员
   }
}

在本程序中先定义了一个外部类的成员变量,接着定义了一个内部类的成员变量,这两个成员变量的名称是相同的。而在内部直接访问时,将访问的是内部类的成员变量。要想访问外部类成员变量,就需要首先创建一个外部类对象,然后使用该对象调用外部类成员变量。

局部内部类

局部内部类的作用范围是和局部变量的作用范围相同的,只在局部中起作用,所以对局部内部类进行访问时,只能在该局部内部类的作用范围内。

举个例子:

class OutClass {public void fun() {    class InClass {    //定义一个局部内部类int i = 5;    //局部内部类的成员变量
        }InClass ic = new InClass();System.out.println("InClass's var is: " + ic.i);}
}
public class javatest {  public static void main(String args[ ]) { OutClass oc = new OutClass();oc.fun();}
}

在本程序中定义了一个局部内部类,并进行了对该局部内部类的访问。对该内部类进行访问必须在该内部类所在的方法中通过创建内部类对象来进行访问。这是因为这里的内部类是作为局部成员的形式出现的,只能在它所在的方法中进行调用。

局部内部类中访问外部类成员变量

在局部内部类中访问外部类成员变量是很容易实现的,并不需要进行过多操作。在局部内部类中可以直接调用外部类的成员变量。

举个例子:

class OutClass {int i = 9;    //定义一个外部类的成员变量public void fun() {    class InClass {    //定义一个局部内部类public void Infun() {System.out.println("OutClass's var is: " + i);    //访问外部类中的成员变量
            }}InClass ic = new InClass();    //创建内部类对象ic.Infun();    //调用内部类中的成员方法
    }
}
public class javatest {  public static void main(String args[ ]) { OutClass oc = new OutClass();    //创建外部类对象oc.fun();    //调用内部类中的成员
   }
}

在示例代码中定义了一个局部内部类,在该局部内部类中定义了一个方法来访问外部类的成员变量。

在局部内部类中访问外部类的局部变量

和访问外部类的成员变量不同,在局部内部类中访问外部类中和局部内部类在同一局部的局部变量是不能够直接访问的。

举个例子(下面是一段错误的代码):

class OutClass {public void OutFun() {int i = 9;class InClass {public void InFun() {System.out.println("OutClass's var is: " + i);//访问外部类的成员变量
            }}InClass ic = new InClass();    //创建内部类对象ic.InFun();    //调用内部类中的成员方法
    }
}
public class javatest {  public static void main(String args[ ]) { OutClass oc = new OutClass();    //创建外部类对象oc.OutFun();    //调用内部类中的成员
   }
}

运行产生异常:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
Cannot refer to a non-final variable i inside an inner class defined in a different method

运行该程序是会发生错误的,错误信息为“从内部类中访问局部变量i;需要被声明为最终类型”。在局部内部类中访问外部类的局部变量是不能够访问普通的局部变量的,必须将该局部变量声明为final。

静态方法中的局部内部类

局部内部类定义在非静态方法和静态方法中是不同的,在前面例子都是将局部内部类定义在非静态方法中,下面就来学习静态方法中定义局部内部类的情况。在静态方法中定义的局部内部类要想访问外部类中的成员,该成员必须是静态成员。

class OutClass {static int i = 4;public static void OutFun() {    //外部类成员class InClass {public void InFun() {System.out.println("OutClass's local var is: " + i);}}InClass ic = new InClass();ic.InFun();}
}
public class javatest {  public static void main(String args[ ]) { OutClass.OutFun();}
}

静态内部类

前面已经学习了非静态内部类,接下来就来学习什么是静态内部类。静态内部类就是在外部类中扮演一个静态成员的角色。创建静态内部类的形式和创建非静态内部类的形式很相似的,只是需要将该内部类使用static修饰成静态的形式。使用static修饰类,这在正常类中是不可能的。定义静态内部类的语法如下所示:
class OutClass {static class InClass {//内部类成员
    }//外部类成员
}

在外部类中访问静态内部类

在外部类中访问静态内部类和在外部类中访问非静态内部类一样的,只需要从成员间访问的角度就可以考虑到这一点。举个例子:

class OutClass {static class InClass {    //创建静态内部类int i = 5;    //内部类成员
    }public void OutFun() {    //外部类成员InClass ic = new InClass();    //创建一个内部类对象int ii = ic.i;    //访问内部类成员System.out.println("static InClass's var is: " + ii);}
}
public class javatest {  public static void main(String args[ ]) { OutClass oc = new OutClass();    //创建外部类对象oc.OutFun();    //调用内部类中的成员
   }
}

在外部类中访问静态内部类和访问非静态内部类是相同的,但是在外部类中访问静态内部类和非静态内部类就不再相同。因为静态内部类是外部类的静态成员,静态成员是不需要外部类对象而存在的,所以在外部类外,对静态内部类进行访问时是不需要创建外部类对象的。

注意:因为静态内部类是外部类的静态成员,静态成员是不需要外部类对象而存在的,所以在外部类外,对静态内部类进行访问时是不需要创建外部类对象的。

匿名内部类

在所有的内部类中最难的就应该是匿名内部类。匿名内部类从名字上看就知道是没有类名的内部类。正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写,

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

创建匿名内部类

在创建匿名内部类中将使用到继承父类或者实现接口的知识,匿名内部类是没有名字的,所以在创建匿名内部类时同时创建匿名内部类的对象。创建匿名内部类的语法格式如下:

new InFather() {//匿名内部类
};

在创建匿名内部类的语法中,InFather是匿名内部类继承的父类的类名,使用new同时创建了匿名内部类的对象。在匿名内部类中可以重写父类中的方法,也可以定义自己的方法。

实例1:不使用匿名内部类来实现抽象方法

abstract class Person {public abstract void eat();
}class Child extends Person {public void eat() {System.out.println("eat something");}
}
public class test {public static void main(String[] args) {Person p = new Child();p.eat();}
}

运行结果:

eat something

可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用。但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类会很麻烦。这个时候就引入了匿名内部类

实例2:匿名内部类的基本实现

abstract class Person {public abstract void eat();
}
public class test {public static void main(String[] args) {Person p = new Person() {public void eat() {System.out.println("eat something");}};p.eat();}
}

运行结果:

eat something

可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写,并且匿名内部类还能用于接口上

实例3:在接口上使用匿名内部类

interface Person {public void eat();
}
public class test {public static void main(String[] args) {Person p = new Person() {public void eat() {System.out.println("eat something");}};p.eat();}
}

运行结果:

eat something

由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现。最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

实例4:Thread类的匿名内部类实现

public class test {public static void main(String[] args) {Thread t = new Thread() {public void run() {for (int i = 1; i <= 5; i++) {System.out.print(i + " ");}}};t.start();}
}

运行结果:

1 2 3 4 5

实例5:Runnable接口的匿名内部类实现

public class test {public static void main(String[] args) {Runnable r = new Runnable() {public void run() {for (int i = 1; i <= 5; i++) {System.out.print(i + " ");}}};Thread t = new Thread(r);t.start();}
}

运行结果:

1 2 3 4 5

参考资料:

1、http://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html

作者:wuyudong
出处:http://www.cnblogs.com/wuyudong/

java学习笔记9--内部类总结相关推荐

  1. Java学习笔记:内部类/匿名内部类的全面介绍

    编写java程序时,一般一个类(或者接口)都是放在一个独立的java文件中,并且类名同文件名(如果类是public的,类名必须与文件名一致:非public得,无强制要求).如果想把多个java类放在一 ...

  2. 【原】Java学习笔记025 - 内部类

    1 package cn.temptation; 2 3 public class Sample01 { 4 public static void main(String[] args) { 5 // ...

  3. 【Java学习笔记之二十六】深入理解Java匿名内部类

    在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...

  4. 尚学堂Java学习笔记

    尚学堂Java学习笔记 ============================ J2SDK&JRE J2SDK:JAVA2 SOFTWARE DEVELOPMENT KIT JRE:JAVA ...

  5. 郑志远的java学习笔记

    郑志远的java学习笔记 郑志远    CCB 1         Java起源 略 2         Java语言概述 1.面向对象编程的3个原则:封装(encapsulation).继承(inh ...

  6. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  7. 2022年Java学习笔记目录

    一.2022年Java任务驱动课程 任务驱动,统摄知识点:2022年Java程序设计讲课笔记 二.2022年Java学习笔记 (一)踏上Java开发之旅 Java学习笔记1.1.1 搭建Java开发环 ...

  8. Java 学习笔记 - 数组类型互转

    Java 学习笔记 - 数组类型互转 数组类型转换 字符串数组 to (Integer.Long.Double)列表 传统方式 Java8 Stream方式 数组 to 数组 字符串数组 to (in ...

  9. c语言/c++转Java学习笔记---基础问题

    c语言/c++转Java学习笔记---基础问题 1.java注释 2.数组的定义和使用 定义 使用 3.类 4.this 的使用 5.继承 6.super的使用 7.包 8.修饰符 成员的访问控制符( ...

最新文章

  1. wireshark出现rst的原因_长水口损毁,其主要原因是这三点造成的
  2. WPF指南之一(WPF的结构)
  3. Mysql+innodb数据存储逻辑
  4. c语言中函数(linux命令查看依赖类库),数组(内存存储是连续的内存空间),Linux下查看a,a[0],a之间的值,可变数组
  5. winowsformshost 的构造函数执行符合指定的绑定约束的_C# 应该允许为 struct 定义无参构造函数...
  6. 18. JSON 操作
  7. Unity2D:简单人物纸娃娃换装实现(一) 服装的变换
  8. windows连接linux共享文件夹,windows访问linux共享文件夹
  9. 黑眼圈订单系统_大熊猫黑眼圈订单后台
  10. 802.1x 命令说明以及配置方法
  11. [重磅]秦雯讲大数据:心动.幡动.风动
  12. 浏览器火狐3.0发布之盛况
  13. mysql表文件与结构_MySQL文件结构、逻辑架构及sql执行流程分析
  14. python监控网站学习笔记2——网页中文乱码
  15. PHP安装(Apache、Mysql、PHP整合)
  16. 西南医科大学口腔医学院•瑞泰口腔奖学金设立
  17. 大数据征信的“是与非”
  18. MySQL数据库存储价格金额使用的数据类型中float、double、decimal的区别
  19. 英特尔NUC迷你电脑套件安装windows10+ubuntu18.04双系统
  20. Azure IoT 技术研究系列4

热门文章

  1. LambdaMART的源码分析:一(MART:回归树)
  2. Java Review - 并发编程_DelayQueue原理源码剖析
  3. Java 8 - 自定义Collector
  4. Keepalived - Keepalived 实现 tomcat双机热备
  5. Apache ZooKeeper - Leader 选举 如何保证分布式数据的一致性
  6. 实战SSM_O2O商铺_42【前端展示】店铺列表页面View层的实现
  7. Kotlin进行异步操作
  8. 查看oracle自定义函数,Oracle自定义函数查询数据字典项
  9. 2021-04-12 电机滑模控制 LuGre摩擦模型
  10. php中怎么定义page,css @page的使用与定义详解