文章目录
- 1.概述
- 2.分类
- 3.静态内部类
- 4.成员内部类
- 5.局部内部类
- 6.匿名内部类(最常用)
1.概述
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内 部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使 用内部类
在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者 称为外部类。
Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完 整的名称。
内部类最大的优点,可以使用外部类私有化数据
2.分类
1.静态内部类
使用static修饰的内部类,相当于静态变量
2.成员内部类
没有static修饰的位于类体的内部类,相当于成员变量
3.局部内部类
方法中声明的内部类
4.匿名内部类(最常用)
3.静态内部类
public class OutterClass{
static class InnerClass{
public static void m1(){
}
public void m2(){
}
}
public static void main(String[] args){
//当前类中类名可以省略
OuterClass.InnerClass.m1();
InnerClass.m1();
InnerClass ic = new OuterClass.InnerClass();
InnerClass ic1 = new InnerClass();
ic.m2();//成员属性必须创建对象才能使用
}
}
注意:
可以使用权限修饰符: private protected public默认
先编译外部类,再编译内部类
类名为:外部类InnerClass
静态内部类中可以有任何申明(静态和成员都可以)
静态内部类中不能直接访问成员属性(需要有对象)
4.成员内部类
public class OuterClass{
private static String s1 = "A";
private String s2 = "B";
class InnerClass{
public void m2(){
public void m2(){
System.out.println(s1);
System.out.println(s2);
}
}
}
public static void main(String[] args){
//外部类
OuterClass oc = new OuterClass();
//创建内部类对象 外部类对象.new内部类();
InnerClass ic = oc.new InnerClass();
ic.m2();
}
}
注意:
可以使用权限修饰符: private protected public默认
先编译外部类,再编译内部类
类名为:外部类InnerClass
成员内部类不能有静态申明
成员内部类可以访问外部类所有的数据
5.局部内部类
public class OuterClass{
privaet static String s1 = "A";
private String s2 = "B";
public void m1(){
// 1.8开始 可以不加final修饰,但是值还是不能更改的
int i = 10;
class InnerClass{
// 不能有静态声明
// public static void m3(){}
public void m4(){
System.out.println(s1);
System.out.println(s2);
System.out.println(i);
}
}
// 局部内部类的使用,必须在该方法中,因为作用域只在该方法中有效
InnerClass in = new InnerClass();
in.m4();
}
public static void m2(){
// 1.8开始 可以不加final修饰,但是值还是不能更改的
int i = 10;
class InnerClass{
// 不能有静态声明
// public static void m3(){}
public void m4(){
System.out.println(s1);
// 需要对象调用
// System.out.println(s2);
System.out.println(new _03_OuterClass().s2);
System.out.println(i);
}
}
// 局部内部类的使用,必须在该方法中,因为作用域只在该方法中有效
InnerClass in = new InnerClass();
in.m4();
}
public static void main(String[] args) {
_03_OuterClass oc = new _03_OuterClass();
oc.m1();
m2();
}
}
注意:
局部内部类,访问外部方法的局部变量的时候,该局部变量必须使用final修饰
但是 1.8开始 final 可以省略,但是值依然不能更改
不管是成员方法还是静态方法,都不能使用static修饰局部内部类
不管是成员方法还是静态方法,局部内部类中都不可以声明静态属性
如果是成员方法的局部内部类,则可以直接访问外部类中的所有属性
如果是静态方法的局部内部类,则不能直接访问成员属性,需要有对象
类名 :
如果多个方法的内部类类名不一致,就是 : 外部类$1内部类
如果多个方法的内部类类名一致,就是 : 外部类$1内部类 , 外部类$2内部类 以此类推
6.匿名内部类(最常用)
public class _04_OuterClass {
public static void main(String[] args) {
String[] strs = { "123", "22", "321", "14" };
// 默认排序 会按照ASCII码值进行比较
// 但是如果我们想按照数值大小排序,就需要自定义规则
// Arrays.sort(strs);
// A a = new A();
// 有一个传入Comparator比较器接口的方法
// 因为接口不能创建对象,所有需要传入接口类型数据的地方,都需要我们传入该接口对应的实现类对象
// 若此时这个实现类不经常使用,或者不被其他地方使用,则可以使用匿名内部类
// Arrays.sort(strs, a);
Arrays.sort(strs, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
System.out.println(this);
String s1 = (String) o1;
String s2 = (String) o2;
return Integer.parseInt(s1) - Integer.parseInt(s2);
}
});
for (String string : strs) {
System.out.println(string);
}
m1(new C());
m1(new B());
m1(new B(){
});
}
public static void m1(B b){
}
}
class B{
}
class C extends B{
}
// class A implements Comparator{
// @Override
// public int compare(Object o1, Object o2) {
// String s1 = (String) o1;
// String s2 = (String) o2;
// return Integer.parseInt(s1) - Integer.parseInt(s2);
// }
// }
注意:
匿名内部类 : 是指在调用方法的时候,需要传入一个对象(一般是接口的实现类对象),
这个时候就可以不传递对象,传递一个匿名内部类
普通类也可以,一般是接口,匿名内部类 就等于是子类
语法 : 方法名(new 接口名(){ 实现类类体; });
传入匿名内部类的时候,会自动创建一个对象传入,因为没有名字,所以不能复用,我们也不能手动创建对象
类名为 外部类类名$1 , 一次类推
匿名内部类中 不能有静态声明 但是可以有常量(public static final)
入一个对象(一般是接口的实现类对象),
这个时候就可以不传递对象,传递一个匿名内部类
普通类也可以,一般是接口,匿名内部类 就等于是子类
语法 : 方法名(new 接口名(){ 实现类类体; });
传入匿名内部类的时候,会自动创建一个对象传入,因为没有名字,所以不能复用,我们也不能手动创建对象
类名为 外部类类名$1 , 一次类推
匿名内部类中 不能有静态声明 但是可以有常量(public static final)
不能直接访问外部类的成员属性,需要有对象