7.6 内部类(了解)
7.6.1 概述
1、什么是内部类?
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
2、为什么要声明内部类呢?
总的来说,遵循高内聚低耦合的面向对象开发总原则。便于代码维护和扩展。
具体来说,当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,不在其他地方单独使用,那么整个内部的完整结构最好使用内部类。而且内部类因为在外部类的里面,因此可以直接访问外部类的私有成员。
3、内部类都有哪些形式?
根据内部类声明的位置(如同变量的分类),我们可以分为:
(1)成员内部类:
-
静态成员内部类
-
非静态成员内部类
(2)局部内部类
-
有名字的局部内部类
-
匿名的内部类
7.6.2 成员内部类
如果成员内部类中不使用外部类的非静态成员,那么通常将内部类声明为静态内部类,否则声明为非静态内部类。
语法格式:
【修饰符】 class 外部类{
【其他修饰符】 【static】 class 内部类{
}
}
1、静态内部类
有static修饰的成员内部类叫做静态内部类。它的特点:
-
和其他类一样,它只是定义在外部类中的另一个完整的类结构
-
可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
-
可以在静态内部类中声明属性、方法、构造器等结构,包括静态成员
-
可以使用abstract修饰,因此它也可以被其他类继承
-
可以使用final修饰,表示不能被继承
-
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名和$符号。
-
-
和外部类不同的是,它可以允许四种权限修饰符:public,protected,缺省,private
-
外部类只允许public或缺省的
-
-
只可以在静态内部类中使用外部类的静态成员
-
在静态内部类中不能使用外部类的非静态成员哦
-
如果在内部类中有变量与外部类的静态成员变量同名,可以使用“外部类名."进行区别
-
-
在外部类的外面不需要通过外部类的对象就可以创建静态内部类的对象(通常应该避免这样使用)
2、非静态成员内部类
没有static修饰的成员内部类叫做非静态内部类。非静态内部类的特点:
-
和其他类一样,它只是定义在外部类中的另一个完整的类结构
-
可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
-
可以在非静态内部类中声明属性、方法、构造器等结构,但是不允许声明静态成员,但是可以继承父类的静态成员,而且可以声明静态常量。
-
可以使用abstract修饰,因此它也可以被其他类继承
-
可以使用final修饰,表示不能被继承
-
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名和$符号。
-
-
和外部类不同的是,它可以允许四种权限修饰符:public,protected,缺省,private
-
外部类只允许public或缺省的
-
-
还可以在非静态内部类中使用外部类的所有成员,哪怕是私有的
-
在外部类的静态成员中不可以使用非静态内部类哦
-
就如同静态方法中不能访问本类的非静态成员变量和非静态方法一样
-
-
在外部类的外面必须通过外部类的对象才能创建非静态内部类的对象(通常应该避免这样使用)
-
如果要在外部类的外面使用非静态内部类的对象,通常在外部类中提供一个方法来返回这个非静态内部类的对象比较合适
-
因此在非静态内部类的方法中有两个this对象,一个是外部类的this对象,一个是内部类的this对象
-
public class TestMemberInnerClass {
public static void main(String[] args) {
Outer.outMethod();
System.out.println("-----------------------");
Outer out = new Outer();
out.outFun();
System.out.println("-----------------------------");
Outer.Inner.inMethod();
System.out.println("------------------------");
Outer.Inner inner = new Outer.Inner();
inner.inFun();
System.out.println("-----------------------------");
Outer outer = new Outer();
// Outer.Nei nei = outer.new Nei();
Outer.Nei nei = out.getNei();
nei.inFun();
}
}
class Outer{
private static String a = "外部类的静态a";
private static String b = "外部类的静态b";
private String c = "外部类对象的非静态c";
private String d = "外部类对象的非静态d";
static class Inner{
private static String a ="静态内部类的静态a";
private String c = "静态内部类对象的非静态c";
public static void inMethod(){
System.out.println("Inner.inMethod");
System.out.println("Outer.a = " + Outer.a);
System.out.println("Inner.a = " + a);
System.out.println("b = " + b);
// System.out.println("c = " + c);//不能访问外部类和自己的非静态成员
// System.out.println("d = " + d);//不能访问外部类的非静态成员
}
public void inFun(){
System.out.println("Inner.inFun");
System.out.println("Outer.a = " + Outer.a);
System.out.println("Inner.a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);
// System.out.println("d = " + d);//不能访问外部类的非静态成员
}
}
class Nei{
private String a = "非静态内部类对象的非静态a";
private String c = "非静态内部类对象的非静态c";
public void inFun(){
System.out.println("Nei.inFun");
System.out.println("Outer.a = " + Outer.a);
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("Outer.c = " + Outer.this.c);
System.out.println("c = " + c);
System.out.println("d = " + d);
}
}
public static void outMethod(){
System.out.println("Outer.outMethod");
System.out.println("a = " + a);
System.out.println("Inner.a = " + Inner.a);
System.out.println("b = " + b);
// System.out.println("c = " + c);
// System.out.println("d = " + d);
Inner in = new Inner();
System.out.println("in.c = " + in.c);
}
public void outFun(){
System.out.println("Outer.outFun");
System.out.println("a = " + a);
System.out.println("Inner.a = " + Inner.a);
System.out.println("b = " + b);
System.out.println("c = " + c);
System.out.println("d = " + d);
Inner in = new Inner();
System.out.println("in.c = " + in.c);
}
public Nei getNei(){
return new Nei();
}
}
静态内部类 | 非静态内部类 | ||
---|---|---|---|
类角色 | 字节码文件 | 外部类名$内部类名 | 相同 |
修饰符 | public,缺省,abstract,final | 相同 | |
父类或父接口 | 可以 | 相同 | |
可以包含的成员 | 所有成员 | 不允许有静态成员 | |
成员角色 | 修饰符 | public、protected、缺省、private,final,static | 没有static |
依赖于外部类 | 依赖 | 相同 | |
依赖于外部类的对象 | 不依赖 | 依赖 | |
使用 | 在外部类中使用内部类 | 没有限制 | 在外部类的静态方法等中不能使用非静态内部类 |
在内部类中使用外部类 | 静态内部类中不能使用外部类的非静态成员 | 没有限制 | |
在外部类的外面使用内部类的静态成员 | 外部类名.静态内部类名.静态成员 | 没有 | |
在外部类的外面使用内部类的非静态成员 | 见下面的框1 | 见下面的框2 | |
重名 | 外部类名.重名的成员名 | 外部类名.this.重名的成员 |
外部类名.静态内部类名 变量 = 外部类名.静态内部类名();
变量.非静态成员();
外部类名 变量1 = new 外部类();
外部类名.非静态内部类名 变量 = 变量1.new 非静态内部类名();
变量.非静态成员();
7.7 注解
7.7.1 什么是注解
注解是以“@注释名”在代码中存在的,还可以添加一些参数值,例如:
@Override
@Deprecated
@SuppressWarnings(value=”unchecked”)
注解Annotation是从JDK5.0开始引入。
虽然说注解也是一种注释,因为它们都不会改变程序原有的逻辑,只是对程序增加了某些注释性信息。不过它又不同于单行注释和多行注释,对于单行注释和多行注释是给程序员看的,而注解是可以被编译器或其他程序读取的一种注释,程序还可以根据注解的不同,做出相应的处理。所以注解是插入到代码中以便有工具可以对它们进行处理的标签。
7.7.2 三个最基本的注解
1、@Override
用于检测被标记的方法为有效的重写方法,如果不是,则报编译错误!
<mark>只能标记在方法上</mark>。
它会被编译器程序读取。
2、@Deprecated
用于<mark>表示被标记的数据已经过时,不建议使用</mark>。
可以用于修饰 <mark>属性、方法、构造、类、包、局部变量、参数</mark>。
它会被编译器程序读取。
3、@SuppressWarnings
抑制编译警告。
可以用于修饰类、属性、方法、构造、局部变量、参数
它会被编译器程序读取。
示例代码:
package com.haogu.annotation;
import java.util.ArrayList;
public class TestAnnotation {
@SuppressWarnings("all")
public static void main(String[] args) {
int i;
ArrayList list = new ArrayList();
list.add("hello");
list.add(123);
list.add("world");
Father f = new Son();
f.show();
f.methodOl();
}
}
class Father{
@Deprecated
void show() {
System.out.println("Father.show");
}
void methodOl() {
System.out.println("Father Method");
}
}
class Son extends Father{
/* @Override
void method01() {
System.out.println("Son Method");
}*/
}