内部类
1.成员内部类
成员内部类又称普通内部类,这是Java之中最常见的内部类
看如下代码:
public class Outer {
private int a = 10;
//int c = b; //将会报错,b为未识别标识符,说明外部类不能访问内部类私有属性
class Inner {
private int b = 5;
public void print() {
System.out.println("访问外部类私有属性a:"+ a);
}
}
public static void main(String[] args) {
//Inner in = new Inner(); //这条语句将会报错
Inner in = new Outer().new Inner();
in.print();
}
}
代码输出为:
访问外部类私有属性a:10
可以总结如下:
1.成员内部类可以访问外部类的私有属性;
2.内部类可以使用任何修饰符,当使用private修饰内部类时,可以体现出封装性;
3.定义了内部类成员后,(非静态内部类)必须通过外部类对象来创建内部类对象,不能直接去new一个内部类对象,正确的格式为:Inner inner = new Outer( ) . new Inner( ) ;
4.切记:外部内不能够直接访问内部类的成员和方法,必须通过创建内部类对象来进行访问;相反的是,内部类可以访问外部类的所有属性 ;
5.成员内部类不能够拥有任何static变量和方法; 但可以访问外部类的静态域;
(分析原因:如果成员内部类拥有了static属性,那么其他类可以直接通过内部类名.属性就可以直接调用,但成员内部类的访问必须依赖于外部类,所以矛盾了)
6.使用内部类可以实现多继承 ,从而避免了Java单继承的缺陷;(代码如下)
class A {
private int age = 20;
public int getAge() { //age为私有属性,则提供方法为外界提取age的值,所以为public
return age;
}
}
class B {
private String name = "yy";
public String getName() {
return name;
}
}
public class Outer {
private class InnerA extends A{ //将这两个类设置为private权限是为了更好的封装;
public int getAge() {
return super.getAge(); //不能直接 return super.age ,因为就算继承了父类,但也不能直接访问父类的私有属性;
}
}
private class InnerB extends B {
public String getName() {
return super.getName();
}
}
public int getAge() {
return new InnerA().getAge(); //除了static属性和方法,其他方法在类外都得通过对象来调用
}
public String getName() {
return new InnerB().getName();
}
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println("Outer类的age为:"+ outer.getAge());
System.out.println("Outer类的name为:"+outer.getName());
}
}
2.静态内部类
所谓静态内部类,就是用static关键字修饰的内部类;可以总结如下:
静态内部类与非静态内部类的最大区别:
非静态内部类在编译完成之后会隐含的保存着一个引用,该引用指向创建它的外围类,但是静态内部类却没有;
没有这个引用才导致静态内部类的创建不依赖于外部类;
1.静态内部类不能直接访问外部类的非静态成员,但可以通过new 外部类( ).成员来进行访问;
2、 如果外部类的静态成员与内部类的成员名称相同 ,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“**成员名”**直接调用外部类的静态成员。
3、 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();
练习代码:
public class Outer {
static int outStatic = 1;
static int sstatic = 20;
private int outerPri = 2;
static class Inner {
static int sstatic = 10;
public void print() {
System.out.println("外部类的静态成员可以直接访问:"+outStatic); //1
//System.out.println("不能直接访问外部类的非静态成员:"+outerPri); //将会报错
System.out.println("通过this关键字调用内部类与外部类同名属性为:"+this.sstatic); //10
System.out.println(("外部的同名属性为:"+Outer.sstatic)); //20
}
}
public static void main(String[] args) {
Inner in = new Inner(); //不用以来外部对象来生成内部类对象
in.print();
System.out.println(Inner.sstatic); //静态属性可直接调用
}
}
运行结果:
外部类的静态成员可以直接访问:1
访问外部类的非静态成员:2
通过this关键字调用内部类与外部类同名属性为:10
外部的同名属性为:20
10
3.方法内部类
方法内部类又称局部内部类,方法内部类与成员内部类基本一致,只是他们的作用域不相同,具体特点如下:
1.方法内部类只能在该方法中被使用,出了该方法就无效;
2.方法内部类不允许使用访问权限修饰符 public、private、protected均不允许;
3.方法内部类对外完全隐藏,除了创建这个类的方法可以访问它,其他的地方是不允许访问的 ;
4.方法内部类要想使用该方法的形参,则可以直接使用(jdk8以后,现在基本都是jdk8以后了),jdk8以前该形参必须用final声名;
练习代码为:
class OuterA {
private int a;
public void print(int num) {
class Inner {
public void fun() {
System.out.println(a); //这个a就是上面的a
System.out.println(num); //打印形参
}
}
new Inner().fun();
}
}
public class Outer {
public static void main(String[] args) {
OuterA out = new OuterA();
out.print(20);
}
}
输出为:
0
20
4.匿名内部类
实质上匿名内部类就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,其他特点如下:
假如要执行的任务需要一个对象,但却不值得创建全新的对象(原因可能 是所需的类过于简单,或是由于他只在一个方法内部使用),匿名类就显得很有用。匿名类尤其适合在Swing应用程式中快速创建事件处理程式。
1.匿名内部类没有访问权限修饰符;
2.匿名内部类必须继承一个抽象类或者实现一个接口;
3.匿名内中不能存在任何static修饰的属性与方法;
4.匿名内部类没有构造方法,因为他没有类名嘛;
练习代码如下:
interface Inter {
void test();
}
class OuterA {
private int a = 10;
public void print(int num) {
new Inter() {
public void test() {
System.out.println("匿名内部类:"+num);
}
}.test();
}
}
public class Outer {
public static void main(String[] args) {
OuterA out = new OuterA();
out.print(20);
}
}
输出:
0
20