内部类定义:什么是内部类? 将一个类的定义放在另一个类的定义内部,这就是内部类。
1.创建内部类方式
//外部类
public class OuterClass{
...
//创建内部类
class InnerClass{
...
}
}
2.在外部类方法中创建内部类对象
public class OuterClass{
class InnerClass{
...
}
// 在外部类里提供一个可返回内部类对象的非静态方法
public InnerClass ns() {
return new InnerClass();
}
//在外部类里提供一个可返回内部类对象的静态方法
static InnerClass to(OuterClass out) {//传递一个外部类对象参数
InnerClass InnerClass = out.new InnerClass();
return InnerClass;
}
}
总结:在外部类非静态方法之外任意位置创建某个内部类对象,需要.new语法提供对外部类对象的引用,例如OuterClassObject.new InnerClassName();
3.内部类拥有对外部类所有元素的访问权与.this
public class OuterClass {
int age = 13;
//提供内部类通过生成外部类引用访问外部类方法
public void tell() {
System.out.println("哈哈");
}
//提供外部类访问内部类private元素
public void callPrivate() {
//必须先实例化内部类对象(非static类)
InnerClass ic = new InnerClass();
System.out.println(ic.innerAge);
}
class InnerClass {
private int innerAge;
public int getAge() {
// return innerAge = OuterAndInner.this.age;
return innerAge = age; // innerAge=13;同上一注释语句
}
public OuterClass outer() {
return OuterClass.this;// 通过.this生成对外部类对象的引用
}
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.callPrivate();
InnerClass inner = outer.new InnerClass();
inner.outer().tell();
}
}
总结:1.在内部类里生成外部类对象引用可通过 OuterClassName.this(即外部类名字.this),内部类可秘密捕捉一个外部类对象引用。
2.内部类可直接访问外部类元素。
3.外部类也可访问内部类private元素。但先必须提供内部类对象引用。4.外部类里的两个内部类可互相访问private元素。但也先必须提供另一个类对象引用。
4.访问内部静态类静态方法和非静态方法
public class OuterClass {
static class InnerClass {
public static void print() {
System.out.println("直接访问静态内部类静态方法");
}
public void read(){
System.out.println("访问静态内部类非静态方法");
}
}
public static void main(String[] args) {
//直接类.类.方法访问静态方法
OuterClass.InnerClass.print();
//通过new 外部类.内部类 创建内部类对象访问非静态方法
new OuterClass.InnerClass().read();
}
}
总结:1.访问内部静态类普通方法,需要 new OuterClass.InnerClass(),创建静态内部类对象。
2.访问内部静态类静态方法,通过层层类名直接调用即可
5.在方法和作用域内的内部类
(1)定义在方法中的类
//import Destination接口
public class Parcel5 {
public Destination destination() {
// 在方法里创建内部类
class PDestination implements Destination {
private String label;
private PDestination(String label) {
this.label = label;
}
public String readLabel() {
return label;
}
}
return new PDestination("方法内部类");// 只能返回其基类对象的引用
}
public static void main(String[] args) {
Parcel5 p5 = new Parcel5();
Destination destination = p5.destination();
}
}
(2)任意作用域内嵌入内部类
public class Parcel5 {
public void destination(boolean b) {
if (b) {
class PDestination{
private String label;
private PDestination(String label) {
this.label = label;
}
public String readLabel() {
return label;
}
}
PDestination pd = new PDestination("dd");
pd.readLabel();
}
//can't use it here ! out of scope
}
}
总结:(1)通过实现某类型接口,创建并返回其对象引用。(2)创建一个类来辅助你的解决方案,但是又不希望这个类是公共可用的。
6.匿名内部类
(1)默认构造函数
//import Contents类
public class AnonyInnerClass {
public Contents contents() {
return new Contents() {
private int i = 11;
public int value() {
return i;
}
};// 此处分号必须加
}
}
(2)有参构造函数
//import Contents类
public class AnonyInnerClass {
public Contents contents(int x) {
return new Contents(x) {
private int i = 11;
public int value() {
return x;
}
};// 此处分号必须加
}
}
总结:contents()将返回值的生成与返回值类的定义结合在一起。这个类是匿名的没有名字。在表达语句分号结束之前插入类的定义。
7.嵌套类
public class NestingClass {
String nameFather="外围类属性";
static String nameStaticFather="外围类静态属性";
//将内部类声明为static -嵌套类
private static class User {
//private String name = nameFather;在静态类里无法访问非静态对象;
String name = nameStaticFather;
public void run() {
System.out.println("会跑");
}
//在静态类里无法使用this链接到外围类对象。类似于静态方法
/*public NestingClass outer(){
return NestingClass.this; //error
}*/
}
//普通内部类
private class User1 {
public void eat() {
System.out.println("会吃饭");
}
}
public static void main(String[] args) {
//
new NestingClass.User().run();
NestingClass nestingClass = new NestingClass();
//实例化内部类需要提供外部类对象
User1 user1 = nestingClass.new User1();
user1.eat();
}
}
总结:嵌套类意味着:1.创建嵌套类对象,并不需要其外围内的对象。2.不能从嵌套类的对象中访问非静态的外围内对象。3.在静态类里无法使用this链接到外围类对象。类似于静态方法。
8.为什么需要内部类
1.一般来说,内部类继承自某个类或实现某个接口,内部类的代码操作创建他的外围内对象。所以可以认为内部类提供了某种进入其外围类的窗口。
2.使用内部类最吸引人原因是:每个内部类都能独立地继承自一个(接口的实现),所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
3.内部类有效地实现了“多重继承”。也就是说,内部类允许继承多个非接口类型(类或抽象类)
9.继承内部类
class OuterClass{
class InnerClass{
}
}
public class TestOut extends OuterClass.InnerClass{
//public OuterClass() {} //不能编译通过
public TestOut(OuterClass out) {
out.super();
}
}
总结:可以看到,TestOut只继承内部类,而不是外围类。但是要当生成一个构造器时,默认的构造器并不算好,而且不能只传递一个外围类对象的引用,必须在构造器里使用如下语法: enclosingClassReference.super();
10.内部类可以被覆盖吗?
总结:当继承了一个外围类,并想重新定义内部类,会发生什么?,“覆盖”内部类就好像一它是外围类的一个方法,其实并不起作用,但是如果明确的继承了某个内部类则可以覆盖。