1、内部类
1.1 实例内部类
- 在类的内部定义,与实例变量、实例方法同级别的类。
- 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象。
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner();- 当外部类、内部类存在重名属性时,会优先访问内部类属性。
- 成员内部类不能定义静态成员。
参考代码:
创建Outer.java
public class Outter {
//实例属性
public int id;
//实例内部类
public class Inner{
public int i_id;
public void test(){
System.out.println("实例内部类的方法");
}
}
}
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
//实例化外部类
Outter outter = new Outter();
//创建内部类对象
Outter.Inner inner = outter.new Inner();
inner.i_id = 10;
System.out.println(inner.i_id);
inner.test();
Outter.Inner inner1 = new Outter().new Inner();
inner1.test();
}
}
1.2 静态内部类
- 不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。
- 只能直接访问外部类的静态成员(实例成员需实例化外部类对象)。
Outter.Inner inner = new Outter.Inner();
inner.test();
参考代码:
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
//调用静态属性
System.out.println(Outter.id);
//调用静态内部类的方法
Outter.Inner inner = new Outter.Inner();
inner.test();
}
}
class Outter{
//静态属性
public static int id;
//静态内部类
static class Inner{
public void test(){
System.out.println("静态内部类");
}
}
}
1.3 局部内部类
- 定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。
- 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final。
- 限制类的使用范围。
参考代码:
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
Outter outter = new Outter();
//局部属性外界无法调用
//outter.test1().id;
outter.test2();
}
}
class Outter{
public void test1(){
//局部属性 -- 不存在访问修饰符
int id = 1;
System.out.println(id);
}
public void test2(){
//局部内部类 -- 作用域只在当前方法中
class Inner{
public void test(){
System.out.println("局部内部类");
}
}
Inner inner = new Inner();
inner.test();
}
}
1.4 匿名内部类
- 没有类名的局部内部类(一切特征都与局部内部类相同)。
- 必须继承一个父类或者实现一个接口。
- 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。
- 优点:减少代码量。
- 缺点:可读性较差。
案例演示:使用接口展示匿名内部类
创建Demo01.java
public class Demo01 {
public static void main(String[] args) {
//使用多态的方式
IInner inner = new Test();
inner.test();
//使用匿名内部类的方式 -- 减少类的数量,当方法只使用一次的时候则可以使用匿名内部类
IInner2 inner2 = new IInner2(){
@Override
public void test() {
System.out.println("匿名内部类");
}
};
inner2.test();
}
}
创建IInner.java
public interface IInner {
void test();
}
创建IInner2.java
public interface IInner2 {
void test();
}
创建Test.java
public class Test implements IInner {
@Override
public void test() {
System.out.println("使用多态的方式");
}
}
案例分析,使用接口回调
创建Demo01.java
package Day11_InnerClass.Iner6;
import Day11_InnerClass.utils.TimeUitls;
/**
* @author wzy
* @version 1.0
* @date 0030 2020-11-30 10:44
*/
public class Demo01 {
public static void main(String[] args) {
/* 第一种方法
// 定义运行前和运行后的时间变量time1和time2;
// 将要测试的代码防止在time2和time2的之间
// time2减去time1的时间即为所求
long time1 = System.currentTimeMillis();
for (int i =0;i<10000;i++){
for (int j=0;j<10000;j++){
for (int k = 0; k <10000 ; k++) {
}
}
}
long time2 = System.currentTimeMillis();
System.out.println("程序运行所用时间:"+(time2-time1));
*/
/* 第二种方法(直接传递对象的方式)
// 实例化Test的对象,
Test test = new Test();
// 将对象传给TimeUitls类的testTime方法 //传递Test的对象
TimeUitls.testTime(test);
*/
/* 第三种方法 (使用匿名内部类)
//
//
//
*/
// 实例化接口ITest的对象test,
ITest test = new ITest() {
@Override
public void test() {
for (int i =0;i<10000;i++){
for (int j=0;j<10000;j++){
for (int k = 0; k <10000 ; k++) {
}
}
}
}
};
TimeUitls.testTime2(test);
}
}
创建ITest.java
package Day11_InnerClass.Iner6;
/**
* @author wzy
* @version 1.0
* @date 0030 2020-11-30 10:43
*/
public interface ITest {
void test();
}
创建Test.java
package Day11_InnerClass.Iner6;
/**
* @author wzy
* @version 1.0
* @date 0030 2020-11-30 10:44
*/
public class Test {
public void test(){
for (int i =0;i<10000;i++){
for (int j=0;j<10000;j++){
for (int k = 0; k <10000 ; k++) {
}
}
}
}
}
2、异常
2.1 概念
异常:程序运行过程中出现的特殊情况
2.2. 异常的必要性
- 任何程序都可能存在大量未知问题、错误
- 如果不对这些问题进行正确处理的话,则可能导致程序中断,造成不必要的损失
2.3 异常分类
Throwable:可抛出的,一切错误或异常的父类,
位于java.lang包中。
- (1)错误
- Error:JVM、硬件、执行逻辑错误,不能手动修改
- 常见错误:StackOverflowError、OutOfMemoryError等
- (2)异常
- Exception:程序在运行和配置中产生的问题,可以处理
1、RuntimeException:运行时异常,可处理,可不处理。
2、CheckedException:检查时异常,必须处理。
常见类型异常:
异常 | 描述 |
---|---|
NullPointerException | 空指针异常 |
ArrayIndexOutOfBoundsException | 数组越界异常 |
ClassCastException | 类型转换异常 |
NumberFormatException | 数字格式化异常 |
ArithmeticException | 算术异常 |
代码参考:
package com.qf.ran.exception1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* Error:错误
* Exception:异常
* 1.一般异常(受检性异常)
* 编写的时候会有异常需要处理
* 2.运行时异常(非受检性异常)
* 编译器不要求处理的异常,只有运行的时候才会出现
*
* 处理异常的方式:
* 1.抛出(声明)异常类型:throws
* 当出现异常,方法会中止运行。
* 当不知道该如何处理异常的时候,向上抛出给调用方,由调用方处理
* 2.捕获异常:
* try{
* 可能会出现异常的代码
* }catch(异常类型 异常对象){
* 处理异常的方式
* }
* 知道如何处理异常的时候使用try/catch,方法的运行不会中断,继续执行
* try块中出现异常,则不再执行try块中剩余的代码,直接结束try块的代码执行
* catch块中的代码
* 可以把catch块中的代码切换成处理异常的代码
* 3.抛出(声明)异常对象:throw
* 更改异常说明信息,让异常定位更准确
*
* 解决异常:了解异常的类型,明白异常出现的原因,寻找异常出现的位置
*/
public class Demo01 { //抛出异常
public static void main(String[] args) throws FileNotFoundException {
//-----------------一般异常(受检性异常)------------------
test();
/*try {
FileInputStream fis = new FileInputStream("");
} catch (FileNotFoundException e) {
e.printStackTrace();
}*/
// ----------------运行时异常(非受检性异常)------------------
//数组下标越界异常 -- ArrayIndexOutOfBoundsException
//int nums[] = {1,2,3};
//print(nums);
//空指针异常 -- NullPointerException
//String str = null;
//不会报空指针异常
//System.out.println("".equals(str));
//报空指针异常
//System.out.println(str.equals(""));
//类型转换异常 -- ClassCastException
//Animal animal = new Animal();
//Dog dog = (Dog)animal;
//数字转换异常 -- NumberFormatException
//String str = "abc";
//int num = Integer.parseInt(str);
//System.out.println(num);
//算术异常 -- ArithmeticException
//int num1 = 1;
//int num2 = 0;
//int num3 = num1/num2;
}
public static void print(int[] nums){
System.out.println(nums[3]);
}
public static void test() throws FileNotFoundException {
System.out.println("异常开始");
FileInputStream fis = new FileInputStream("io.txt");
System.out.println("异常结束");
}
}
class Animal{
}
class Dog extends Animal{
}
2.4 异常的产生
- 自动抛出异常:当程序运行遇到不合理的代码时或者结果时,会产生异常
- 手动抛出异常:语法: thorw new 异常类型(“实际参数”)
- 产生异常结果:相当于遇到return语句,导致程序因异常而终止
2.5 异常传递
- 异常的传递:
- 按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈跟踪信息)。
- 受查异常:throws 声明异常,修饰在方法参数列表后端。
- 运行时异常:因可处理可不处理,无需声明异常。
案例演示:异常的产生、传递。
public class Demo02 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("io.txt");
} catch (FileNotFoundException e) {
//抛出异常对象
try {
throw new FileNotFoundException("com.qf.ran.exception2的Demo02的第15代码出错了");
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
/*
自定义异常
try {
throw new FileException("io.txt文件还没创建");
} catch (FileException e1) {
e1.printStackTrace();
}*/
}
}
}
2.6 异常处理
java通过5个关键字来实现对异常的处理
- try:执行可能会产生异常的代码
- catch:捕获异常,并处理
- finally:无论是否发生异常,finally的代码均会执行
- throw:手动抛出异常
- thorws:声明方法可能要抛出的各种异常
try…catch…
语法:
try {
//可能出现异常的代码
} catch(Exception e) {
//异常处理的相关代码,如:getMessage()、printStackTrace()
}
public class Demo06 {
public static void main(String[] args) throws FileNotFoundException {
System.out.println("异常开始");
File file=new File("C:\\Users\\Public\\Desktop");
FileOutputStream fileOutputStream = new FileOutputStream(file);
try{
int nums[] = {1,2,3};
System.out.println(nums[8]);
}catch (Exception e){
System.out.println(e.getClass());
System.out.println(e.getMessage());
System.out.println(e.getCause());
}
}
}
try…catch…finally…
语法:
try {
//可能出现异常的代码
} catch(Exception e) { //异常处理的相关代码,如:getMessage()、printStackTrace()
} finally{
//是否发生异常都会执行,可以释放资源等。
}
public class Demo01 {
//try/catch后面接finally,finally则一定会执行
public static void main(String[] args) {
System.out.println("异常开始");
int num = 0;
try {
int[] nums = {1,2,3};
//会报ArrayIndexOutOfBoundsException
System.out.println(nums[3]);
System.out.println("a");
//会报FileNotFoundException
FileInputStream fis = new FileInputStream("io.txt");
System.out.println("b");
num = 10;
} catch (Exception e) {
//e.printStackTrace();
//手动提示语句
System.out.println("小老弟,出异常啦,赶紧找你老大");
//一定执行的代码
}finally {
num = 10;
}
System.out.println("异常结束");
System.out.println("num:"+num);
}
}
多重catch
语法:
try{
//可能出现异常的代码。
}catch(异常类型1){
//满足异常类型1执行的相关代码。
}catch(异常类型2){
//满足异常类型2执行的相关代码。
}catch(异常类型3){
//满足异常类型3执行的相关代码
}
public class Demo03{
public static void main(String[] args) {
System.out.println("异常开始");
try {
int[] nums = {1,2,3};
//会报ArrayIndexOutOfBoundsException
//System.out.println(nums[3]);
System.out.println("a");
//会报FileNotFoundException
FileInputStream fis = new FileInputStream("io.txt");
System.out.println("b");
} catch (FileNotFoundException e ) {
//e.printStackTrace();
//手动提示语句
System.out.println("小老弟,出异常啦,赶紧找你老大");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("出数组下标越界异常啦");
}
System.out.println("异常结束");
}
}
2.7 异常中方法覆盖
带有异常声明的方法重写:
- 方法名、参数列表、返回值类型必须和父类相同。
- 子类的访问修饰符合父类相同或是比父类更宽。
- 子类中的方法,不能抛出比父类更多、更宽的检查时异常。
创建Demo02.java
package Day11_Exception.exception2;
import Day11_Exception.exception2.FileException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* @author Ran
* @since JDK 1.8
*
* 抛出异常对象
*/
public class Demo02 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("io.txt");
} catch (FileNotFoundException e) {
//抛出异常对象
// try {
// throw new FileNotFoundException("com.qf.ran.exception2的Demo02的第15代码出错了");
// } catch (FileNotFoundException e1) {
// e1.printStackTrace();
// }
//自定义异常 thorw new 自定义类型,传入参数
try {
throw new FileException("io.txt文件还没创建");
} catch (FileException e1) {
e1.printStackTrace();
}
}
}
}
创建FileException.java
package Day11_Exception.exception2;
import java.io.FileNotFoundException;
/**
* @author wzy
* @version 1.0
* @date 0030 2020-11-30 15:06
*/
public class FileException extends FileNotFoundException {
public FileException(String str){
super(str);
}
}