1.把一个类放在另一类内部定义,这个定义在其他类里面的类就叫做内部类,包含内部类的类叫做外部类。内部类成员可以直接访问外部类的私有数据,但是外部类不能访问内部类的实现细节。

2.非静态内部类(没有static修饰的内部类)

package cn.lsl;

public class Cow {
private double weight;
public Cow(){}
public Cow(double weight){
this.weight = weight;
} private class CowLeg{
private double length;
private String color;
public CowLeg(double length, String color) {
super();
this.length = length;
this.color = color;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void info(){
System.out.println("颜色:" + color + ",高:" + length);
System.out.println("重:" + weight);
}
} public void test(){
CowLeg cl = new CowLeg(2, "红色");
cl.info();
} public static void main(String[] args) {
Cow cow = new Cow(123);
cow.test();
}
}

System.out.println("重:" + weight);这句代码在非静态内部类里可以直接访问外部类的private成员。
当调用非静态内部类的实例方法时,必须有一个静态内部类实例,而非静态内部类实例必须寄存在外部类实例里。

3.如果在外部类、内部类、内部类里方法里面出现了同名的变量,则可以通过this、外部类类名.this来访问

package cn.lsl;

public class Variable {
private String a = "外部类实例变量";
private class In{
private String a = "内部类实例变量";
public void info(){
String a = "局部变量";
System.out.println("外部类:" + Variable.this.a);
System.out.println("内部类:" + this.a);
System.out.println("局部变量:" + a);
}
}
public void test(){
In in = new In();
in.info();
} public static void main(String[] args) {
new Variable().test();
}
}

三种访问形式:
System.out.println("外部类:" + Variable.this.a);
System.out.println("内部类:" + this.a);
System.out.println("局部变量:" + a);

4.外部类不能直接访问非静态内部类的实例Field,如果外部类需要访问非静态内部类的成员,则必须显示创建非静态内部类对象来调用访问其实例成员。

package cn.lsl;

public class Outer {
private int a = 5;
class In{
private int b = 23;
public void accessOuter(){
System.out.println("直接访问外部类的a的值" + a);
}
} public void accessIn(){
//System.out.println("内部类b的值:" + b); 编译出错,不能直接访问
System.out.println("内部类b的值:" + new In().b);
} public static void main(String[] args) {
Outer out = new Outer();
out.accessIn();
}
}

非静态内部类对象必须寄存在外部类对象里面,而外部类对象不一定要有非静态内部类对象寄存其中。即,如果存在一个非静态内部类对象,一定要存在一个被它寄存的外部类对象。
5.静态内部类(使用static修饰的内部类)
(1)如果使用static修饰一个内部类,则这个内部类就属于外部类本身,不属于外部类的某个对象。
(2)静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。

package cn.lsl;

public class StaticIn{
private int a = 5;
private static int b = 23;
static class In{
private static int age;
public void accessOut(){
//System.out.println(a); //编译出错
System.out.println(b);
}
}
}

(3)外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员

package cn.lsl;

public class StaticIn{
static class In{
private static int a = 5;
private int b = 23;
} public void accessIn(){
// System.out.println(a); //编译出错
System.out.println(In.a);
// System.out.println(b); //编译出错
System.out.println(new In().b);
}
}

6.在外部类以外使用非静态内部类
如果希望在外部类以外的地方访问内部类,则内部类不能使用private访问控制权限,private修饰的内部类只能在外部类内部使用。
非静态内部类的对象必须寄存在外部类的对象里,因此创建非静态内部类之前,必须先创建其外部类对象。

eg:
package cn.lsl; class Out {
class In{
public In(String msg){
System.out.println(msg);
}
}
} public class CreateIn{
public static void main(String[] args) {
Out.In in = new Out().new In("测试信息");
}
}

在外部类以外的地方创建非静态内部类实例必须使用外部类实例和new来调用非静态内部类的构造器。
7.在外部类以外使用静态内部类
因为静态内部类是外部类类相关的,因此创建内部类对象时无须创建外部类对象。

package cn.lsl;

class StaticOut{
static class In{
public In(){
System.out.println("静态内部类的构造器");
}
}
}
public class CreateStaticOut {
public static void main(String[] args) {
StaticOut.In in = new StaticOut.In();
}
}

静态内部类和非静态内部类声明变量的语法是一样的,区别在于创建内部类对象时,静态内部类只需使用外部类即可调用构造器,而非静态内部类必须使用外部类对象来调用构造器。

8.局部内部类
如果把一个内部类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类仅在该方法里有效。
由于局部内部类不能再方法以外的地方使用,因此局部内部类也不能使用访问控制符和static修饰符修饰。
如果需要用局部内部类定义变量,创建实例或派生子类,那么都只能在局部内部类所在的方法内进行。

package cn.lsl;

public class LocalIn {
public static void main(String[] args) {
class InnerBase{
int a;
}
class InnerSub extends InnerBase{
int b;
}
InnerSub is = new InnerSub();
is.a = 5;
is.b = 8;
System.out.println(is.a + "," + is.b);
}
}

9.匿名内部类
(1)匿名内部类适合创建那种只需要一次使用的类,创建匿名内部类时会立即创建一个该类的实例,这个类定义即消失,匿名内部类不能重复使用。
(2)匿名内部类的格式

new 父类构造器(实参列表)|实现接口(){

}

(3)匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。
(4)匿名内部类不能是抽象类。
(5)匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器。但匿名内部类可以定义实例初始化块,通过实例初始化块来完成构造器需要完成的事情。

package cn.it.lsl;

interface Product{
public double getPrice();
public String getName();
} public class AnonymousTest{
public void test(Product p){
System.out.println("购买" + p.getName() + ",花掉了" + p.getPrice());
}
public static void main(String[] args) {
AnonymousTest ta = new AnonymousTest();
ta.test(new Product(){ @Override
public double getPrice() {
// TODO Auto-generated method stub
return 190;
} @Override
public String getName() {
// TODO Auto-generated method stub
return "声卡";
}
});
}
}

test()方法需要传入一个Product对象作为参数,但Product只是一个接口,因此此处考虑创建一个Product接口实现类的对象传入该方法。
上面匿名内部类部分也可以等价于下面这段代码

public class AnonymousTest implements Product{
@Override
public double getPrice() {
// TODO Auto-generated method stub
return 100;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return "声卡";
} public void test(Product p){
System.out.println("购买" + p.getName() + ",花掉了" + p.getPrice());
} public static void main(String[] args) {
AnonymousTest ta = new AnonymousTest();
ta.test(new AnonymousTest());
}
}

10.如果通过继承父类来创建匿名内部类,匿名内部类将拥有和父类相似的构造器,此处的相似指的是拥有相同的形参列表。

package cn.it.lsl;
abstract class Device{
private String name;
public abstract double getPrice();
public Device(){}
public Device(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class AnonymousInner {
public void test(Device d){
System.out.println("购买一个" + d.getName() + ",花掉了" + d.getPrice());
} public static void main(String[] args) {
AnonymousInner ai = new AnonymousInner();
ai.test(new Device("鼠标"){ @Override
public double getPrice() {
// TODO Auto-generated method stub
return 23;
}
});
Device d = new Device() {
{
System.out.println("匿名内部类初始化块");
} @Override
public double getPrice() {
// TODO Auto-generated method stub
return 32;
} //重写父类的实例方法
public String getName(){
return "键盘";
}
};
ai.test(d);
}
}

当创建匿名内部类时,必须实现接口或抽象父类里的所有抽象方法。如果有需要,也可以重写父类中的普通方法。
11.如果匿名内部类需要访问外部类的局部变量,则必须使用final修饰符来修饰外部类的局部变量

package cn.it.lsl;
interface A{
void test();
}
public class ATest {
public static void main(String[] args) {
//int age = 0;
final int age = 0;
A a = new A(){ @Override
public void test() {
System.out.println(age); } };
}
}

Java笔记:内部类的更多相关文章

  1. java 笔记(2) —— 内部类的作用

    一.内部类简介 个人觉得内部类没多少研究价值,GUI中的事件响应算是非常典型的应用了. Java内部类其实在J2EE编程中使用较少,不过在窗口应用编程中特别常见,主要用来事件的处理.其实,做非GUI编 ...

  2. Thinking in Java 笔记

    大二就买了这本书,如今再看这本书,看到了一些以前没看的细节,也有了不同的体会.本文使用第4版,整理每章的笔记心得.老外的书有个特点,他会花费大量的文字去阐述一个概念,这比堆代码强多了. 第 1 章 对 ...

  3. java笔记整理

    Java 笔记整理 包含内容     Unix Java 基础, 数据库(Oracle jdbc Hibernate pl/sql), web, JSP, Struts, Ajax Spring, E ...

  4. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  5. Java学习--内部类(一)

    Java学习--内部类(一) 一. 内部类的定义和特点 class Outer{ privite int num = 5; class Inner{ public void Display(){ Sy ...

  6. Java的内部类

    Java的内部类 首先我们来了解一下什么是内部类? 内部类是指在一个外部类的内部再定义一个类.内部类可以是静态static的,也可用public,default,protected和private修饰 ...

  7. java笔记00-目录

    --2013年7月26日17:49:59 学习java已久,趁最近有空,写一个总结: java笔记01-反射:

  8. java使用内部类的好处及其初始化

    java使用内部类的原因 每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响          java内部类初始化 ForeCatal ...

  9. JAVA基础——内部类详解

    JAVA内部类详解 在我的另一篇java三大特性的封装中讲到java内部类的简单概要,这里将详细深入了解java内部类的使用和应用. 我们知道内部类可分为以下几种: 成员内部类 静态内部类 方法内部类 ...

  10. JAVA面向对象-----内部类的概述

    JAVA面向对象-–内部类的概述s 将类定义在另一个类的内部则成为内部类.其实就是类定义的位置发生了变化. 在一个类中,定义在类中的叫成员变量,定义在函数中的叫成员函数,那么根据类定义的位置也可以分为 ...

随机推荐

  1. ffmpeg参数具体解释

    a) 通用选项 -L license -h 帮助 -fromats 显示可用的格式,编解码的.协议的... -f fmt 强迫採用格式fmt,如image2.gif -i filename 输入文件 ...

  2. 进程切换switch_to宏第三个参数分析

    进程切换一般都涉及三个进程,如进程a切换成进程b,b开始执行,但是当a恢复执行的时候往往是通过一个进程c,而不是进程b. 注意switch_to的调用: switch_to(prev,next,pre ...

  3. C--运算符,表达式和语句实例

    //第五章 运算符,表达式和语句 #include<stdio.h> //引入头文件 #include<math.h> #define ADJUST 7.64 //定义常量 # ...

  4. cform 开发框架介绍

    CForm是从2012年开始研发的一套灵活,易用,简单,成熟的中小型应用系统开发框架.目前已成功应用在浙江大学.温州科技职业学院.广西农业局.青岛市农业局.乐清妇保院.老博会.婚尚起义结婚网等单位. ...

  5. userAgent,JS这么屌的用户代理,你造吗?——判断浏览器内核、浏览器、浏览器平台、windows操作系统版本、移动设备、游戏系统

    1.识别浏览器呈现引擎 为了不在全局作用域中添加多余变量,这里使用单例模式(什么是单例模式?)来封装检测脚本.检测脚本的基本代码如下所示: var client = function() { var ...

  6. div、ul、li等无法居中问题,text-align无效 margin auto无效

    很简单.如果是div,直接把div换成: <table align="center">        <tr>            <td> ...

  7. 纯Lambda实现斐波那契数列

    还需要考虑溢出等问题,主要无事写着玩 Func<float, float, float> a = (arg1, arg2) => 0f;//init ; a = (lastNumbe ...

  8. Session变量不能转移到下页.解决: session.use_trans_sid = 1

    附:文摘 ============================================================ 在PHP使用SESSION的朋友可能会碰到这么一个问题.SESSIO ...

  9. iOS文档序列化(对象归档)

    对象归档: 概念: 对象归档是指将对象写入文件保存在硬盘,当再次又一次打开程序时,能够还原这些对象.也称:对象序列化.对象持久化. 数据持久性的方式(事实上就是3类) 1,NSKeyedArchive ...

  10. 探秘ReSharper8.1版本中Architecture(架构工具)的改进

    在ReSharper 8.0新版本中,有一个叫做Architecture(结构工具)的新功能,此功能被定义为项目依赖关系分析.其目的是让用户可视化操作解决方案的结构.接下来,小编将在ReSharper ...