总结:
1、内部类可以操作外部类中所有的成员方法和成员变量,包括private修饰过的。Java编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着,这样就使得内部类对象始终可以访问其外部类对象。
2、任何非静态内部类中,都不能有静态数据。
3、编译完成后,内部类的字节码文件的格式是:外部类名$内部类名。
4、当外部类、内部类、内部类方法中都包含同一字段或方法时,当方法调用那个字段或方法,首先调用的是方法中的字段,如果想调用类中的字段,可以用:this.字段名,如果想调用外部类中的字段,可以用:outer.this.字段名。
5、声明内部类:
To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Because you are actually inside the class which also is the outerObject you just use "this" instead of the outerObject.In instance methods of the outer class you can create an inner class object with simply "new" and its enclosing object will automatically be "this."
创建非静态内部类对象,一定要先创建起相应的外部类对象,这样做的好处是体现了封装性,也可以在外部类定义一个返回内部类对象的方法来实现。
public class Outer {
private int age = 10;
private Inner in1 = new Inner();//在外部类中,直接定义内部类对象
Outer(){}
Outer(int value){age = value;System.out.println("Outer.age:"+age);}
public void print(){
System.out.println("Outer.age:"+age);
}
public Inner getInnerInstance(){
return new Inner();//返回内部类的一个引用
}
class Inner{
private int age = 34;
Inner(){System.out.println("Outer.Inner");}
public void print(){
int age = 23;
System.out.println("#:"+age);//调用的是方法中的字段
System.out.println("##:"+this.age);//调用内部类中的字段
System.out.println("###:"+Outer.this.age);//调用外部类中的字段
}
}
//当main方法在 外部类 的内部
public static void main(String[] args) {
System.out.println("in1...");
Outer out = new Outer();
out.in1.print();
// in1.print();//编译错误:Connot make a static reference to the non-static field in1
System.out.println("in2...");
Inner in2 = out.getInnerInstance();//可以直接引用,不需要属性引用符
in2.print();
System.out.println("in4...");
Outer.Inner in4 = out.new Inner();
in4.print();
System.out.println("in6...");
Inner int6 = new Outer().new Inner();
int6.print();
}
}
class TestInner{
//当main方法在 外部类 的外部
public static void main(String[] args){
System.out.println("in3...");
Outer out = new Outer();
Outer.Inner in3 = out.getInnerInstance();//内部类作为其外部类的一个成员(注意与in2 比较)
// Outer.Inner in = new Inner();//编译错误,不能直接用new去声明内部类,编译错误:Inner connot be resolved to a type.
System.out.println("in5...");
Outer.Inner in5 = out.new Inner();
in5.print();
// in1.print();//编译错误:in1 connot be resolved
// out.in1.print();//编译错误:out.in1 connot be resolved,因为Inner是private修饰的,只能够在Outer内部进行访问
}
}
6、内部类的继承
当一个类继承自一个内部类时,缺省的构造器不可用。因为每一个内部类都有一个指向外部类的引用,在继承一个内部类,必须先创建一个外部类,通过这个外部类引用来调用其内部类的构造方法。如果继承的内部类是一个静态内部类,则就不需要这样,直接super()调用即可。
class TestExtend extends Outer.Inner{
TestExtend(Outer out){
out.super();
}
public static void main(String[] args){
Outer out = new Outer();
TestExtend ex = new TestExtend(out);
ex.print();
}
}
内部类可以被重载吗?注意,当你继承了某个外围类的时候,内部类并没有发生什么特别神奇的变化。这两个内部类是完全独立的两个实体,各自在自己的命名空间内。
class OtherOuter extends Outer{
class Inner {
Inner(){System.out.println("OtherOuter.Inner");}
public void print(){
System.out.println("OtherOuter.print()");
}
}
public static void main(String[] args){
OtherOuter other = new OtherOuter();
other.new Inner().print();
}
}
输出:
Outer.Inner
OtherOuter.Inner
OtherOuter.print()
可以明确地继承某个内部类,只要添加extends Outer.Inner
class OtherOuter extends Outer{
class Inner extends Outer.Inner{//
Inner(){System.out.println("OtherOuter.Inner");}
public void print(){
System.out.println("OtherOuter.print()");
}
}
public static void main(String[] args){
OtherOuter other = new OtherOuter();
other.new Inner().print();
}
}
输出:
Outer.Inner
Outer.Inner
OtherOuter.Inner
OtherOuter.print()
7、内部类的重要应用
一个类从另一个类派生出来,又要实现一个接口。但在接口中定义的方法与父类中定义的方法的意义不同,则可以利用内部类来解决这个问题。
interface People{
void print();
}
class Parents{
public void print(){System.out.println("Parents...");}
}
class Child extends Parents{
class PeopleImpl implements People{
public void print() {//public不可缺少
System.out.println("Override People.print");
}
}
PeopleImpl getPeopleImpl(){
return new PeopleImpl();
}
}
class Test3{
public static void main(String[] args){
Child c = new Child();
c.print();//打印结果:Parents...
c.getPeopleImpl().print();//打印结果:Override People.print
}
}
类似的,内部类可以解决C++多重继承所解决的问题。在实际应用中,内部类又可以实现很多软件工程思想,比如:
class DataStructure {
private final static int SIZE = 15;
private int[] arrayOfInts = new int[SIZE];
public DataStructure() {
for (int i = 0; i < SIZE; i++) {
arrayOfInts[i] = i;
}
}
public void printEven() {
InnerEvenIterator iterator = this.new InnerEvenIterator();//创建内部类遍历
while (iterator.hasNext()) {
System.out.print(iterator.getNext() + " ");
}
}
private class InnerEvenIterator {
private int next = 0;
public boolean hasNext() {
return (next <= SIZE - 1);
}
public int getNext() {
int retValue = arrayOfInts[next];
next += 1;
return retValue;
}
}
public static void main(String s[]) {
DataStructure ds = new DataStructure();
ds.printEven();//结果:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
}
}
特殊的内部类,除了具有普通内部类的特点,还有自己的一些独有特性
1、静态内部类:将内部类声明为static。要创建嵌套类的对象,并不需要其外围类的对象。
Outer.Inner in = new Outer.Inner(); 不能从嵌套类的对象中访问非静态的外围类对象(包括静态变量和静态方法)。静态内部类中可以定义静态或者非静态的成员。
2、局部内部类:在方法中定义的内部类称为局部内部类。只能访问方法中的final类型的局部变量,局部内部类不允许有访问修饰符。
3、匿名内部类:顾名思义,没有名字的内部类。匿名内部类为局部内部类,所以局部内部类的所有限制对其都有效,除此之外还要注意以下几个原则:
(1)匿名内部类必须扩展一个基类或实现一个接口,但是不能有显式的extends和implements子句。
(2)匿名内部类必须实现父类以及接口中的所有抽象方法。
(3)匿名内部类不能有构造方法,总是使用父类的无参构造方法来创建实例。如果是实现了一个接口,则其构造方法是Object()。
(4)匿名内部类编译后的命名为:OuterClass$n.class,其中n是一个从1开始的整数,如果在一个类中定义了多个匿名内部类,则按照他们的出现顺序从1开始排号。
(5)匿名内部类不能定义任何静态成员、方法和类。
class Parcel {
public Outer cont() {
return new Outer() {//创建一个继承Outer的匿名类
private int age = 11;
public void print() {
System.out.println("Parcel.age:"+age);
}
}; // 在这里需要一个分号
}
public Outer cont(int age){//不要求变量age 一定是final 的。因为age 被传递给匿名类的基类的构造器,它并不会在匿名类内部被直接使用。
return new Outer(age){
private int age = 21;
public void print() {
System.out.println("Parcel.age:"+age);
}
};
}
/*
* 参数若没有final,编译报错:"Cannot refer to a non-final variable value inside an
* inner class defined in a different method."
* 匿名内部类,它要使用一个在它的外部定义的对象,编译器会要求其参数引用是final 型的
*/
public Outer cont2(final int value){
return new Outer(value){
private int age = value;
public void print() {
System.out.println("Parcel.age:"+age);
}
};
}
public static void main(String[] args) {
Parcel p = new Parcel();
Outer c = p.cont();
c.print();//结果:Parcel.age:11
c=p.cont(7);//因为7 被传递给匿名类的基类的构造器,它并不会在匿名类内部被直接使用
c.print();//Outer.age:7 Parcel.age:21
}
}
相关面试题收集:
1、Anonymous Inner Class(匿名内部类)是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?
匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,
但一个内部类可以作为一个接口,由另一个内部类实现。
2、Static Nested Class 和 Inner Class的不同
答:Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。
Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。
注: 静态内部类(Inner Class)意味着
1)创建一个static内部类的对象,不需要一个外部类对象,
2)不能从一个static内部类的一个对象访问一个外部类对象
分享到:
相关推荐
### Java基础复习知识点详解 #### 一、Java语言特点 - **高级编程语言**:Java是一种面向对象的高级编程语言,具有以下特点: - **简单性**:语法简洁,易于学习。 - **结构中立**:独立于硬件结构,能够在各种...
JAVA理论知识基础复习涵盖了JAVA语言的基础知识,包括构造方法、new关键字、方法的重载、特殊变量this、static定义常量、继承、方法的重写、特殊变量super、多态性、接口和抽象类的区别、内部类和异常处理等相关知识...
复习时,可以详细阅读`Java抽象类.docx`来理解抽象类的定义、用途和实例化规则,通过`Java接口.docx`学习接口的定义、实现方式以及多继承的特点,`Java内部类.docx`将帮助你掌握不同类型的内部类及其应用场景。...
### JAVA基础知识复习面试笔试宝典 #### 面向对象基础 **面向对象**与**面向过程**是两种常见的编程思想。面向过程的核心是过程、步骤或函数,它以过程为核心,强调的是如何去做;而面向对象的核心是对象,它以...
### JAVA基础课程复习材料知识点详解 #### 一、内部类概述 内部类是Java语言中一个重要的特性,它允许在类的内部定义另一个类。这种内部定义的类被称为内部类,而包含它的类则被称为外部类。内部类的使用极大地提高...
以下是对Java基础的详细解析: 1. **Java简介**: Java是由Sun Microsystems公司(现已被Oracle收购)开发的一种面向对象的编程语言,以其“一次编写,到处运行”的跨平台特性而闻名。Java应用广泛,包括桌面应用...
这份“Java基础知识复习资料”涵盖了学习Java编程所必需的关键概念和技术,旨在帮助初学者巩固基础,同时也适合有经验的开发者进行回顾。 1. **Java语法基础** - **变量与数据类型**:Java提供了基本数据类型(如...
这些知识点通常会出现在公司内部的JAVA基础复习题中,通过练习这些题目,开发者可以巩固理论知识,提升实际编程技能。每个xls文件可能包含了针对上述知识点的不同题目,通过解答,可以帮助你更好地准备公司的Java...
以上内容只是Java基础的冰山一角,深入学习还需要掌握异常处理、集合框架、IO流、多线程编程、网络编程以及数据库连接等更多主题。对于初学者来说,理解并熟练掌握这些基础知识是成为专业Java开发者的必要步骤。
### Java考试复习资料详解 #### 一、架构模式:B/S与C/S - **B/S架构**(Browser/Server,浏览器/服务器)是一种通过Web浏览器进行访问的应用系统架构。客户端只需要一个Web浏览器即可,无需安装任何软件。所有的...
【Java基础】 Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems(现已被Oracle公司收购)于1995年发布。Java以其“一次编写,到处运行”的特性,成为跨平台应用开发的首选语言。Java的基础部分主要包括...
本文总结了Java期末复习习题和答案,涵盖了Java基础知识点、变量和数据类型、控制结构、方法、类和对象、异常处理、输入输出和类库等方面的知识点,为Java初学者和有一定基础的学习者提供了有价值的参考。
在“硅谷java基础每日复习eDiary”这个资源中,我们涵盖了Java编程语言的基础和高级概念,这将有助于深入理解并提升Java编程技能。以下是基于描述中提到的两个文件——"Java基础每日复习笔记-JavaSE基础阶段.edf"和...
Java网络编程基础复习题涵盖了许多Java编程的基础概念,包括标识符规则、数据类型、赋值语句、编译错误、继承机制、访问修饰符、成员变量的访问、类与对象以及内部类的相关知识。以下是对这些知识点的详细解释: 1....
文件I/O操作也是Java基础的重要部分。Java提供了File类来处理文件,以及InputStream和OutputStream家族来读写数据。流的概念使得数据可以从一个源传输到另一个目的地。 最后,集合框架是Java中管理对象数组的强大...
Java编程语言复习重点整理 1. **访问修饰符的区别**: - `public`:所有类都可以...这些知识点涵盖了Java基础中的核心概念,对于理解和编写Java代码至关重要。复习这些内容有助于提升对Java语言的理解和应用能力。
### Java面试复习资料详解 #### 一、内存泄漏与内存溢出 - **内存泄漏**:指程序在申请内存后,无法释放已分配的内存空间,导致随着时间的推移,程序所消耗的内存逐渐增加。这通常是因为程序员未能正确地管理内存...
Java是一种强类型语言,这意味着在编写Java代码时,变量必须先声明并初始化...以上是对Java基础知识的一些关键点的详细解释,涵盖了类型系统、变量、访问控制和一些核心特性。这些内容对于理解Java编程的基础至关重要。
期末复习对于学习Java的学生来说至关重要,因为这能帮助他们巩固所学知识,为考试做好充分准备。本资料包包含了“java期末复习13题及答案”,旨在帮助学生理解和解决常见的Java编程问题。 1. **基础语法**: - ...