目录
内部类的目的就是为了提高安全性!
在Java中,可以将一个类定义在另一个类里面或者一个方法里边,这样的类称为内部类,广泛意义上的内部类一般包括四种:成员内部类,局部内部类,匿名内部类,静态内部类 。
1.成员内部类
特点:在一个类的内部定义一个内部类。
public class NormInner {
private int age = 88;
final static String name = "tom";
class Inner {
public void m1() {
System.out.println("age" + age + ",name=" + name);
}
}
public static void main(String[] args) {
NormInner normInner = new NormInner();
normInner.new Inner().m1();
}
}
(1)该类像是外部类的一个成员,可以无条件的访问外部类的所有成员属性和成员方法(包括private成员和静态成员);
(2)成员内部类拥有与外部类同名的成员变量时,会发生隐藏现象,即默认情况下访问的是成员内部类中的成员。如果要访问外部类中的成员,需要以下形式访问:【外部类.this.成员变量 或 外部类.this.成员方法】;
(3)在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问;
(4)成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象;
(5)内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。如果成员内部类用private修饰,则只能在外部类的内部访问;如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。外部类只能被public和包访问两种权限修饰。
2.局部内部类
特点:1.在方法中定义一个内部类。2.不能用public和private修饰。3.对外界完全隐藏。4.可以访问被声明为final的局部变量。
public class InnerClass2 {
public static void main(String[] args) {
final int age = 88;//必须final修饰
final String name = "tom";
class Inner {
public void m1() {
System.out.println("age" + age + ",name=" + name);
}
}
new Inner().m1(); //局部内部类只能在方法内部中使用
}
}
(1)局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内;
(2)局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
3.匿名内部类
特点:1.不能有构造方法。2.不能定义任何静态的成员、方法、类,但是可以定义非静态的方法、属性、内部类。3.一定跟在new后面,创立其实现的接口或父类对象。4.只能创建一个实例。
public class Sort {
public static void main(String[] args) {
String[] array = new String[]{"abc", "abcd", "ab", "abed"};
System.out.println("排序前:" + Arrays.toString(array));
Arrays.sort(array, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
System.out.println("排序后:" + Arrays.toString(array));
}
}
(1)一般使用匿名内部类的方法来编写事件监听代码;
(2)匿名内部类是不能有访问修饰符和static修饰符的;
(3)匿名内部类是唯一一种没有构造器的类;
(4)匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
4.静态内部类
特点:1.属于外部类本身,不属于外部类某个对象。2.可以用public,protected,private修饰。3.只能访问外部类静态成员。4.被static修饰的成员内部类成为静态内部类。
package xw;
public class Outer {
//定义一个实例变量和一个静态变量
private int a;
private static int b;
//定义一个静态方法和一个非静态方法
public static void say(){}
public void test(){
//在外部类中调用内部类的属性和方法
Outer.Inner.c = 1; //可以通过静态内部类的全类名来调用静态内部类的静态属性(外部类名.静态内部类名.属性)
Outer.Inner.go(); //可以通过静态内部类的全类名来调用静态内部类的静态方法(外部类名.静态内部类名.方法)
//Outer.Inner.walk(); //不能通过类静态内部类的全类名来调用内部类的非静态属性和方法
Inner inner = new Inner();
inner.d = 1;
inner.walk(); //可以通过创建内部类实例来调用静态内部类的非静态属性和方法
}
//静态内部类
public static class Inner{
//在静态内部类中定义一个静态变量和一个实例变量
static int c;
int d;
//定义一个匿名代码块和一个静态代码块
{}
static{}
//定义一个静态方法和一个普通方法
public static void go(){}
public void walk(){
//在静态内部类中调用外部类的属性和方法
int f = b; //可以直接调用外部类的静态属性
say(); //可以直接调用外部类的静态方法
//int e = a; 直接调用外部类的非静态属性出错编译出错
//test(); 直接调用外部类的非静态方法时编译出错
Outer outer = new Outer();
int e = outer.a; //可以通过创建外部类实例来调用外部类的非静态属性
outer.test(); //可以通过创建外部类实例来调用外部类的非静态方法
}
}
}
(1)不能在静态内部类中写抽象方法
(2)外部类如何调用静态内部类中的属性和方法
1)外部类可以通过创建静态内部类实例的方法来调用静态内部类的非静态属性和方法
2)外部类可以直接通过“ 外部类.内部类.属性(方法)” 的方式直接调用静态内部类中的静态属性和方法
(3)静态内部类如何调用外部类的属性和方法
1)静态内部类可以直接调用外部类的静态属性和方法
2)静态内部类可以通过创建外部类实例的方法调用外部类的非静态属性和方法
(4)如何创建静态内部类实例
1)在非外部类中:外部类名.内部类名 name = new 外部类名.内部类名();
2)在外部类中:内部类名 name = new 内部类名();