1.Java基础-异常泛型匿名内部类集合

Posted Ocean:)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.Java基础-异常泛型匿名内部类集合相关的知识,希望对你有一定的参考价值。

项目

数据库管理系统StudentSystemV1.0

包名结构:
	cn.system.student.ocean888.entity	
        --实体类			Student.java
	cn.system.student.ocean888.manager	
        --管理类			StudentManager.java
	cn.system.student.ocean888.test		
        --测试类			SystemTest.java
	cn.system.student.ocean888.mainProject	
        --main方法所在类		Index.java

eclipse复制项目tips:

  1. 打开项目所在目录

image-20210514134530578

image-20210514134600559

  1. 复制项目文件夹

image-20210514134628581

  1. 改名

image-20210514134716271

文件夹名和.project文件中的name值都要改

  1. 导入项目

鼠标右击,import导入项目,选择更名之后的项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sr6ajbXV-1623306038338)(F:_笔记\\mdpic\\1.Java基础(三)]\\image-20210514134905335.png)

导入成功

image-20210514135001438

异常

Throwable类

Java中所有异常的超类,在Java中所有的异常,错误的基类就是Throwable类

Throwable

  • Exception 异常
  • Error 错误

Throwable常用方法

Constructor:

  • Throwable()

    Throwable构造方法,Throwable类对象中,存储的异常或者错误信息默认为null

  • Throwable(String message)

    Throwable构造方法,Throwable类对象中,存储的异常或者错误信息为message

Method:

  • String getMessage()

    获取Throwable对象中存储的异常或者错误信息

  • String toString()

    返回当前异常或者错误的简要描述

  • void printStackTrace()

    展示错误的前因后果,[字体是红色的]

package cn.ocean888_a;

public class Demo1 {
	public static void main(String[] args) {
		Throwable throwable = new Throwable("test");
		
		System.out.println(throwable.getMessage());
		System.out.println(throwable.toString());
//		throwable.printStackTrace();
	}
}

image-20210605214042792

throwable.printStackTrace

image-20210605214111058

package cn.ocean888_a;

public class Demo1 {
	public static void main(String[] args) {
		Throwable throwable = new Throwable("test");
	
		test();
	}
	
	public static void test() {
		new Throwable("throwableTest").printStackTrace();
	}
}

image-20210605214320258

Exception和Error

Exception 异常可以处置

Error 错误,不可处置,只能避免

异常处理

捕获异常

try catch 结构

try catch finally结构

package cn.ocean888_a;

public class Demo1 {
	public static void main(String[] args) {
		int[] arr = new int[10];
		// 算数异常
		div(10, 0, arr);
		// 算数异常
		div(10, 0, null);
		// 空指针异常
		div(10, 2, null);
	}
	
	public static void div(int num1, int num2, int[] arr) {
		try {
			arr[0] = num1 /num2;
		} catch (ArithmeticException e) {
			System.out.println("算数异常");
		} catch (NullPointerException e) {
			System.out.println("空指针异常");
		}
	}
}

image-20210605221632056

总结:

  1. 代码中从异常发生的位置开始,之后的代码都不再执行
  2. 代码中有多个异常,可以使用多个catch块进行捕获操作,分类进行处理
  3. 后期可以将异常情况保存下来作为log日志文件
  4. 异常被捕获之后代码可以正常运行

抛出异常

  • throw

    方法内抛出异常

  • throws

    在方法声明位置,告知调用者当前方法有哪些异常抛出

    异常声明需要生成对应的文档注释

package cn.ocean888_a;

public class Demo1 {
	public static void main(String[] args) throws ArithmeticException, NullPointerException {
		int[] arr = new int[10];
		try {
			div(10, 0, null);
		} catch (ArithmeticException e) {
			System.out.println(e);
		} catch (NullPointerException e) {
			System.out.println(e);
		}
	}
	
	/**
	 * 测试除法函数
	 * @param num1 被除数
	 * @param num2 除数
	 * @param arr 保存数组
	 * @throws ArithmeticException 算数异常
	 * @throws NullPointerException 空指针异常
	 */
	public static void div(int num1, int num2, int[] arr) throws ArithmeticException, NullPointerException {
	
		if(num2 == 0) {
			// 除数为零算数异常
			throw new ArithmeticException("算数异常");
		}
		
		if(arr == null) {
			// 数组空指针异常
			throw new NullPointerException("空指针异常");
		}
		
		System.out.println(num1 / num2);
		arr[0] = num1 / num2;
	}
}

image-20210605224109330

抛出异常总结:

  1. 一个代码块{}内,有且只能有一个异常
  2. 从throw位置开始,之后的代码不在运行
  3. 代码中存在使用throw抛出异常,在方法声明位置必须告诉调用者这里有什么异常

RuntimeException

运行时异常

image-20210606120649974

自定义异常

自定义异常类名:必须以Exception结尾

package cn.ocean888_a;

public class Demo2 {
	public static void main(String[] args) {
		// 抛出异常
		try {
			buyOneFreeOne(false);
		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	public static void buyOneFreeOne(boolean single) throws NoGirlFriendException{
		if(single) {
			throw new NoGirlFriendException();
		}
		System.out.println("买一送一");
	}
}


// 自定义异常
class NoGirlFriendException extends Exception {
	// 无参数构造方法
	public NoGirlFriendException() {}
	
	// 有参数构造方法
	public NoGirlFriendException(String message) {
		super(message);
	}
}

image-20210606132516702

泛型genericity

image-20210606134049711

格式:

<自定义泛型无意义大写英文字母占位符>

例:<T> Type <E> Element <K> Key <V> value

反省可以在方法,类,接口中使用

泛型在方法中使用

使用静态方法的泛型格式:

public static <T> 返回值类型[自定义泛型] 方法名(必须存在一个对应泛型的参数) {
    方法体内可以使用泛型
}
package cn.ocean888;

public class Demo1 {
	public static void main(String[] args) {
		Integer test = test(123);
		String test2 = test("你好");
		Demo1 test3 = test(new Demo1());
	}
	
	/**
	 * 带有自定义泛型的声明方法
	 * @param <T> 自定义泛型无意义占位符
	 * @param t 指定的泛型数据类型,由用户约束
	 * @return 对应的T类型,具体数据类型由用户约束
	 */
	public static <T> T test(T t) {
		return t;
	}
}

整型时

image-20210606141015385

字符串型

image-20210606141048425

总结:

  1. 自定义泛型声明在返回值之前,以保证方法的参数和返回值都可以使用对应的泛型
  2. 方法声明的泛型,在方法中的参数中必须有一个参数是对应声明的自定义泛型,当前参数是用于约束方法内所用使用到泛型的位置对应的具体数据类型是什么
package cn.ocean888;

public class Demo1 {
	public static void main(String[] args) {
		Integer test = test(123);
		String test2 = test("你好");
		Demo1 test3 = test(new Demo1());
		
		Integer[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
		String[] arr2 = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
		printArray(arr1);
		printArray(arr2);
	}
	
	/**
	 * 带有自定义泛型的声明方法
	 * @param <T> 自定义泛型无意义占位符
	 * @param t 指定的泛型数据类型,由用户约束
	 * @return 对应的T类型,具体数据类型由用户约束
	 */
	public static <T> T test(T t) {
		return t;
	}
	
	public static <T> void printArray(T[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}
}

image-20210606143555977

泛型在类中使用

格式

class 类名<自定义泛型无意义大写字母占位符> {
    在类内的成员变量和成员方法都可以使用自定义泛型
    建议:成员变量不建议使用自定义泛型
}
package cn.ocean888;

import java.awt.Window.Type;

/**
 * 定义一个自定义泛型类
 * @author Ocean
 *
 * @param <T>
 */
class TypeA<T> {
	/**
	 * 使用和类名一致的自定义泛型,需要通过 类对象 来约束
	 * @param t 对应泛型具体数据类型的参数
	 * @return 对应泛型具体数据类型的返回值
	 */
	public T test1(T t) {
		return t;
	}
	
	public void test2(T t1, T t2) {
		System.out.println(t1);
		System.out.println(t2);
	}
}

public class Demo2 {
	public static void main(String[] args) {
		/*
		 * 创建带有自定义泛型类的对象
		 * TypeA<String> typeA = new TypeA<String>(); Eclipse标准写法
		 * TypeA<String> typeA = new TypeA<>(); IDEA写法
		 */
		
		// 明确告诉编译器,这里泛型对应的具体数据类型是String类型
		// 类内所有使用到泛型占位符的位置都是T类型
		TypeA<String> typeA = new TypeA<String>();
		String test1 = typeA.test1("Paking duck");
		System.out.println(test1);
		typeA.test2("meat", "fruit");
		
		// 明确告诉编译器,这里泛型对应的具体数据类型是Demo2类型
		TypeA<Demo2> typeA2 = new TypeA<Demo2>();
		Demo2 test2 = typeA2.test1(new Demo2());
		System.out.println(test2);
		
	}
}

image-20210606163623358

image-20210606163706359

image-20210606163714047

不推荐这种方法

注意:

  1. 类声明自定义泛型,需要通过创建对象的方式来约束

    TypeA<String> typeA = new TypeA<String>(); Eclipse标准写法
    TypeA<String> typeA = new TypeA<>(); IDEA写法
    
  2. 类声明泛型约束之后,在类内的所有成员方法中使用的泛型都是类约束的泛型具体数据类型

  3. 如果没有约束类声明泛型,所有使用到泛型的位置都是object(不推荐使用)

  4. 类声明的自定义泛型不能用于类内的静态方法

    因为静态成员方法是在类文件的加载阶段准备完毕,已经可以明确的保证该方法是可以执行的

    如果使用类声明的自定义泛型,对应泛型的具体数据类型需要在创建类对象之后才可以明确

    当前静态方法在类文件加载阶段无法明确泛型数据类型是哪一个,也就无法保证执行,因为没有对象

泛型在接口中使用

interface 接口名<自定义泛型无意义占位符> {
    
}
package cn.ocean888;

interface A<T> {
	void test(T t);
}

/**
 * 自由方式,类名之后和接口同名自定义泛型,泛型对应的数据类型是需要在创建当前对象时进行约束使用
 * 
 * @author Ocean
 *
 * @param <T> 遵从接口和接口一致的泛型
 */
class TypeB<T> implements A<T> {
	@Override
	public void test(T t) {
		System.out.println("自由模式");
	}
}

/**
 * 规矩模式,遵从接口时,接口使用泛型对应的具体数据类型已经明确
 * 在类内使用接口中缺省属性为public abstract方法时,泛型已经确认
 * @author Ocean
 *
 */
class TypeC implements A<String> {
	@Override
	public void test(String t) {
		System.out.println("规矩模式");
	}
}


public class Demo3 {
	public static void main(String[] args) {
		/*
		 * 自由模式
		 */
		TypeB<Integer> typeB = new TypeB<Integer>();
		typeB.test(10);
		
		TypeB<Character> typeB2 = new TypeB<Character>();
		typeB2.test('A');
		
		/*
		 * 规矩模式
		 */
		TypeC typeC = new TypeC();
		typeC.test("test");
	}
}

image-20210607141542399

  1. 接口声明的泛型,只能用于类内的成员方法

  2. 遵从带有自定义泛型的接口的类,一种可以遵从过程中明确告知泛型具体类型(规矩模式),一种是在创建类对象时明确泛型具体数据类型(自由模式)

    image-20210607143008661

匿名内部类

Anonymous Inner Type

几种方法的比较

package cn.ocean888_b;

import java.security.PublicKey;

/*
 * 匿名内部类
 */

interface A {
	void test();
}

/**
 * 非abstract修饰TypeA遵从接口A,要求强制实现接口中的test方法
 */
class TypeA implements A {
	@Override
	public void test() {
		System.out.println("普通接口");
	}
}

public class Demo1 {
	public static void main(String[] args) {
		// 一般接口实现
		TypeA typeA = new TypeA();
		typeA.test();
		
		
		/*
		 * A接口的引用a,new调用A接口的构造方法,注意:并不是创建A接口对象
		 * 大括号{}里面的内容和一个普通类遵从接口A的效果是一模一样的
		 * 大括号里面的内容可以认为是类的 本体,但是大括号之前没有类名,这就是匿名内部类
		 * 
		 * new 关键字在内存堆区申请了空间,创建了一个隐含的遵从接口A的匿名内部类对象
		 * 并且把该对象的空间首地址,赋值给了接口A的引用数据类型变量
		 * 接口的引用遵从接口的类对象,这就是多态
		 */
		A a = new A() {
			@Override
			public void test() {
				System.out.println("匿名内部类的对象赋值给接口的引用");
			}
		}; // 一定注意这里有分号
		a.test();
		
		
		// 匿名内部类的匿名对象直接调用方法
		new A() {
			@Override
			public void test() {
				System.out.println("匿名内部类的匿名对象直接调用方法");
			}
		}.test();
		
		
		// 匿名内部类的匿名对象直接调用方法的参数,推荐使用此方式
		testInterface(new A() {
			@Override
			public void test() {
				System.out.println("匿名内部类的匿名对象直接调用方法的参数");
			}
		});
	}
	
	/**
	 * 需要接口A的实现类对象作为方法的参数
	 */
	public static void testInterface(A a) {
		a.test();
	}
}

之前项目的排序就可以用匿名内部类的方法去实现

image-20210609211040462

	@Test
	public void testSortAge() {
		StudentManager studentManager = new StudentManager();

		studentManagerjava基础第七天_匿名内部类异常包和jar

Java泛型和内部类

Java 基础系列合集

java基础总结 -- 泛型 在类接口方法匿名类元组等使用 堆栈例子 商店模型

java基础总结 -- 泛型 在类接口方法匿名类元组等使用 堆栈例子 商店模型

使用 lambda 而不是显式匿名内部类时的不同泛型行为