为何使用内部类
1、内部类提供了更好的封装,只有外部类能访问内部类2、内部类可以独立继承一个接口,不受外部类是否继承接口影响
3、内部类中的属性和方法即使是外部类也不能直接访问,相反内部类可以直接访问外部类的属性和方法,即使private
4、利于回调函数的编写
在Java中内部类主要分为
1、成员内部类2、局部内部类
3、匿名内部类
4、静态内部类
内部类与外部类之间的关系
内部类是一个相对独立的实体,与外部类不是is-a关系内部类可以直接访问外部类的元素,但是外部类不可以直接访问内部类的元素(包括私有元素)
成员内部类
成员内部类也是最普通的内部类,它是外部类的一个成员,所以他是可以无限制的访问外围类的所有成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。在成员内部类中要注意两点:
成员内部类中不能存在任何static的变量和方法
成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类
若变量名相同,则用“外部类名.this.变量名”,若不相同,直接用变量名进行访问。
class Outer{
//外部类的成员变量
private int num = 10 ;
//成员内部类
class Inner{
public void show() {
System.out.println(num);
}
}
}
public class OuterDemo {
public static void main(String[] args) {
//格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
局部内部类
方法内部类定义在外部类的方法中,局部内部类和成员内部类基本一致,只是它们的作用域不同,方法内部类只能在该方法中被使用,出了该方法就会失效。 对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,调用局部变量时,局部变量需要用final修饰。
若变量名相同,则用“外部类名.this.变量名”,若不相同,直接用变量名进行访问。
public class Parcel {
private void internalTracking(boolean b){
if(b){
class TrackingSlip{
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip(){
return id;
}
}
//方法内使用
TrackingSlip ts = new TrackingSlip("chenssy");
String string = ts.getSlip();
}
}
public void track(){
internalTracking(true);
}
public static void main(String[] args) {
Parcel parcel = new Parcel();
parcel.track();
}
}
匿名内部类
其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,初次之外,还有一些地方需要注意:匿名内部类是没有访问修饰符的。
匿名内部类必须继承一个抽象类或者实现一个接口
匿名内部类中不能存在任何静态成员或方法
匿名内部类是没有构造方法的,因为它没有类名。
程序示例:
public class Button {
public void click(){
//匿名内部类,实现的是ActionListener接口
new ActionListener(){
public void onAction(){
System.out.println("click action...");
}
}.onAction(); //分号结尾
}
//匿名内部类必须继承或实现一个已有的接口
public interface ActionListener{
public void onAction();
}
public static void main(String[] args) {
Button button=new Button();
button.click();
}
}
换一种书写方式
public class Button {
public static ActionListener click(){
//匿名内部类,实现的是ActionListener接口
return new ActionListener(){
public void onAction(){
System.out.println("click action...");
}
}; //分号结尾
}
//匿名内部类必须继承或实现一个已有的接口
public interface ActionListener{
public void onAction();
}
public static void main(String[] args) {
button.click().onAction();
}
}
抽象类和接口本来是不可以new操作的,但是此处可以,那是因为new 和 实现同时进行了。匿名 new 接口时,相当于new了一个实现了此接口的对象。匿名new抽象类时,相当于new了一个继承了此抽象类的子类对象。然后,对象可以调用其对应的方法。
静态内部类
1.声明在类体部,方法体外,并且使用static修饰的内部类2.访问特点可以类比静态变量和静态方法
3.脱离外部类的实例独立创建
在外部类的外部构建内部类的实例
new Outer.Inner();
在外部类的内部构建内部类的实例
new Inner();
4.静态内部类体部可以直接访问外部类中所有的静态成员,包含私有
public class StaticInnerTest {
public static void main(String[] args) {
//外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
StaticOuter.StaticInner si = new StaticOuter.StaticInner();
si.test2();
System.out.println("si.b = "+si.b);
System.out.println("si.a = "+si.a);
}
}
class StaticOuter {
private int a = 100;
private static int b = 150;
public static void test(){
System.out.println("Outer static test ...");
}
public void test2(){
System.out.println("Outer instabce test ...");
}
static class StaticInner {
public int a = 200;
static int b =300;
public static void test(){
System.out.println("Inner static test ...");
}
public void test2(){
System.out.println("Inner instance test ...");
StaticOuter.test();
new StaticOuter().test2();
System.out.println("StaticOuter.b = "+StaticOuter.b);
}
}
}