Java基础语法09-面向对象下-内部类-注解-异常
(1)成员内部类:
-
静态成员内部类
-
非静态成员内部类
(2)局部内部类:
-
有名字的局部内部类
-
匿名的内部类
【修饰符】 class 外部类 【extends 父类】 【implements 接口们】{
【其他修饰符】 static class 静态内部类 【extends 父类】 【implements 接口们】{
}
}
静态内部类的权限修饰符:四种,其他修饰符:abstract或final + static
2、静态内部类也是类
(1)可以有自己的父类或父接口
(2)有自己的字节码文件:外部类名$静态内部类名.class
(3)有自己的成员:没有限制
只要在类中可以写的成员它都可以有,只有静态内部类允许有静态成员。
3、静态内部类的使用
(1)静态内部类使用外部类的成员时:
有限制:静态内部类不能使用外部类的非静态成员
(2)在外部类中使用静态内部类
使用静态内部类的静态成员:直接使用“静态内部类名."
使用静态内部类的非静态成员:使用“静态内部类的对象."
(3)在外部类的外面使用静态内部类
前提:这个静态内部类在外面是可见,否则只能通过这个静态内部类的父类或父接口来引用它的对象。
如果可见,使用静态内部类的静态成员:直接使用“外部类名.静态内部类名."
使用静态内部类的非静态成员:使用“静态内部类的对象."
【修饰符】 class 外部类 【extends 父类】 【implements 接口们】{
【其他修饰符】 class 非静态内部类 【extends 父类】 【implements 接口们】{
}
}
非静态内部类的权限修饰符:四种,其他修饰符:abstract或final
2、非静态内部类也是类
(1)可以有自己的父类或父接口
(3)有自己的成员:有限制
不能有静态成员,除非静态常量。
3、非静态内部类的使用
(1)非静态内部类使用外部类的成员时:没有限制
(2)在外部类中使用非静态内部类
在外部类的静态成员中使用无法使用非静态内部类的。
在外部类的非静态成员中使用非静态内部类,使用“非静态内部类的对象."
在非静态内部类的方法中有两个this对象,一个是外部类的this对象,一个是内部类的this对象
(3)在外部类的外面使用非静态内部类
前提:这个非静态内部类在外面是可见,否则只能通过这个非静态内部类的父类或父接口来引用它的对象。
如果可见,使用非静态内部类的非静态成员:要求必须有外部类的对象的引用
外部类 out = new 外部类(【...】);
外部类.非静态内部类 对象名 = out.new 非静态内部类(【...】);
【修饰符】 class 外部类 【extends 父类】 【implements 接口们】{
【修饰符】 返回值类型 方法名(【形参列表】){
【abstract或final或没有】 class 局部内部类 【extends 父类】 【implements 接口们】{
}
}
}
局部内部类没有权限修饰符,其他修饰符:abstract或final
局部内部类的特点:
-
和外部类一样,它只是定义在外部类的某个方法中的另一个完整的类结构
-
可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
-
可以在局部内部类中声明属性、方法、构造器等结构,但不包括静态成员,除非是从父类继承的或静态常量
-
-
可以使用final修饰,表示不能被继承
-
编译后有自己的独立的字节码文件,只不过在内部类名前面冠以外部类名、$符号、编号。
-
这里有编号是因为同一个外部类中,不同的方法中存在相同名称的局部内部类
-
-
-
和成员内部类不同的是,它前面不能有权限修饰符等
-
局部内部类如同局部变量一样,有作用域
-
局部内部类中是否能访问外部类的静态还是非静态的成员,取决于所在的方法
-
局部内部类中还可以使用所在方法的局部常量,即用final声明的局部变量
-
JDK1.8之后,如果某个局部变量在局部内部类中被使用了,自动加final
-
在外部类中使用局部内部类
有作用域,即只能在这个方法体中,并且在声明之后。
在外部类的外面使用局部内部类:不能
在外部类的外面可以得到局部内部类的对象
但是需要通过它的父类或父接口的变量来引用,用方法的返回值返回。
父类/父接口 变量 = new 父类/父接口(【实参列表】){
//可以写方法....
};
new 父类/父接口(【实参列表】){
//可以写方法....
}.方法(【实参列表】);
方法名(new 父类/父接口(【实参列表】){
//可以写方法....
});
所有局部内部类的限制都适用于匿名内部类。例如:
-
-
在匿名内部类中如果需要访问当前方法的局部变量,该局部变量需要加final
思考:这个对象能做什么呢?
答:(1)调用某个方法(2)赋值给父类/父接口的变量,通过多态引用使用这个对象(3)作为某个方法调用的实参
和普通注释不同:注解的注释内容是可以被另一段程序读取的
一个完整的注解应该有三个部分:
(1)声明: @interface
(2)使用: @注解名 或 @注解名(....)
(3)读取:
-
-
CLASS:可以由类加载器读取
-
RUNTIME:可以通过反射的代码在运行时读取
1、@Override
用于检测被修饰的方法为有效的重写方法,如果不是,则报编译错误!
只能标记在方法上。
2、@Deprecated
用于表示被标记的数据已经过时,不建议使用。
可以用于修饰 属性、方法、构造、类、包、局部变量、参数。
3、@SuppressWarnings
抑制编译警告。
可以用于修饰类、属性、方法、构造、局部变量、参数
格式:
@SuppressWarnings("all") @SuppressWarnings("uncheck") @SuppressWarnings({"unused","uncheck"})
-
@author 标明开发该类模块的作者,多个作者之间使用,分割
-
@version 标明该类模块的版本
-
@see 参考转向,也就是相关主题
-
@since 从哪个版本开始增加的
-
@param 对方法中某参数的说明,如果没有参数就不能写
-
-
@throws/@exception 对方法可能抛出的异常进行说明 ,如果方法没有用throws显式抛出的异常就不能写
-
其中 @param @return 和 @exception 这三个标记都是只用于方法的。
-
@param的格式要求:@param 形参名 形参类型 形参说明
-
@return 的格式要求:@return 返回值类型 返回值说明
-
@exception 的格式要求:@exception 异常类型 异常说明
-
@param和@exception可以并列多个
-
javadoc.exe就是这些注解的信息处理流程。
如果导出时有乱码问题,可以指定字符编码
-docencoding UTF-8
-encoding UTF-8
-charset UTF-8
- @Test:标记在非静态的测试方法上。
-
-
@AfterClass:标记在静态方法上。因为这个方法只执行一次。在所有方法@Test方法完成后执行。
-
@Before:标记在非静态方法上。在@Test方法前面执行,而且是在每一个@Test方法前面都执行
-
@After:标记在非静态方法上。在@Test方法后面执行,而且是在每一个@Test方法后面都执行
-
@BeforeClass、@AfterClass、@Before、@After都是配合@Test使用的,单独使用没有意义。
(1)@Target:用于描述注解的使用范围
-
可以通过枚举类型ElementType的10个常量对象来指定
(2)@Retention:用于描述注解的生命周期
-
可以通过枚举类型RetentionPolicy的3个常量对象来指定
-
唯有RUNTIME阶段才能被反射读取到。
(3)@Documented:表明这个注解应该被 javadoc工具记录。
(4)@Inherited:允许子类继承父类中的注解
@元注解
【修饰符】 @interface 注解名{
数据类型 参数名1();
数据类型 参数名2() default 默认值;
}
(1)声明时,类型有要求:
8种基本数据类型、String、枚举、Class、注解,以及他们的数组
(2)使用时
可以在定义 Annotation 的成员变量时为其指定初始值, 指定成员变量的初始值可使用 default 关键字
自定义注解必须配上注解的信息处理流程才有意义。
对于异常,一般有两种解决方法:一是遇到错误就终止程序的运行。另一种方法是由程序员在编写程序时,就考虑到错误的检测、错误消息的提示,以及错误的处理。
如果要自定义异常,必须继承Throwable或它的子类
1、try:尝试执行可能会发生异常的代码
2、catch:尝试捕获try中发生的异常
3、finally:无论try中是否发生异常,也无论catch是否可以捕获异常,也不管try和catch中是否有return语句,都要执行。除非在try或catch中执行了System.exit(0)语句。
4、throw:用于手动抛出异常
5、throws:表示某个方法内部没有处理xx异常,抛给调用者处理,在方法的签名中显式声明抛出哪些异常
try{
可能发生异常的代码
}catch(异常类型 e){
处理异常的代码
//打印,或什么都不写,或者其他处理代码
}catch(异常类型 e){
处理异常的代码
//打印,或什么都不写,或者其他处理代码
}finally{
...
}
try:该代码块中编写可能产生异常的代码。
catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。
-
可以有多个catch块,按顺序匹配。
-
如果多个异常类型有包含关系,那么小上大下
注意:finally不能单独使用。当只有在try或者catch中调用退出JVM的相关方法,例如System.exit(0),此时finally才不会执行,否则finally永远会执行。
一般我们是使用一次捕获多次处理方式
注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。
-
-
如果finally有return语句,永远返回finally中的结果,避免该情况.
-
如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
-
父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类方法中产生了编译时异常,只能捕获处理,不能声明抛出
要求:
1、必须继承Throwable或它的子类,一般继承Exception或RuntimeException
2、尽量保留两个构造器:无参和有参(message)
3、加序列化版本ID
4、自定义异常类型的对象只能使用throw语句抛出