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. .NET Framework 各版本区别

    .NET Framework 各版本区别 .NET Framework 1.1 自1.0版本以来的改进:自带了对mobile asp .net控件的支持.这在1.0版本是以附加功能方式实现的,现在已经 ...

  2. IBM、京东、携程、eBay 的 OpenStack 云

    我所了解的 IBM.京东.携程.eBay 的 OpenStack 云 参加过几次 OpenStack meetup 活动,听过这几家公司的Architect 讲他们公司的 OpenStack产品.本文 ...

  3. 浅谈 js eval作用域

    原文:浅谈 js eval作用域 就简单聊下如何全局 eval 一个代码. var x = 1; (function () { eval('var x = 123;'); })(); console. ...

  4. 原生js写的一个弧形菜单插件

    弧形菜单是一种半弧式或者全弧形菜单,是一种不同于传统横向或者竖向菜单形式的菜单.最近在网上看到好多人写出了这种效果,于是也尝试自己写了一个. 实现方式:原生态js 主要结构: 1.参数合并 var d ...

  5. sql点滴37—mysql中的错误Data too long for column '' at row 1

    原文:sql点滴37-mysql中的错误Data too long for column '' at row 1   1.MYSQL服务 我的电脑——(右键)管理——服务与应用程序——服务——MYSQ ...

  6. mcstructs-MircoCStructs用C语言实现的微型数据结构库

    以C语言的方式,我将逐步实现以下算法: 我的Github地址为:https://github.com/tfa2012/mcstructs 1 线性链表 2 环形缓冲区 3 Hash表

  7. [译]Java 设计模式之迭代器

    (文章翻译自java-design-pattern-iterator) 迭代器模式用于迭代遍历一个集合对象.它是一个经常被用到的模式,你可能以前使用过它.不管在任何时候你看见一些方法像hasNext( ...

  8. leetcode 第42题 Multiply Strings

    题目:Given two numbers represented as strings, return multiplication of the numbers as a string. Note: ...

  9. windows下架设SVN服务器并设置开机启动

    原文:windows下架设SVN服务器并设置开机启动 1.安装SVN服务器,到http://subversion.apache.org/packages.html上下载windows版的SVN,并安装 ...

  10. iis7 下配置MVC问题

    HTTP 错误 404.0 - Not Found 您要找的资源已被删除.已更名或暂时不可用. 详细错误信息 模块 IIS Web Core 通知 MapRequestHandler 处理程序 Sta ...