这周学习了设计模式,内部类,异常的相关概念知识.
一.设计模式概念
1.定义
Java 包含23种设计模式,是一套对代码设计经验的总结,被人们反复利用,多人熟知的代码设计方式.
2.目的
为了提高代码的可读性,可扩展性以及复用性,为了解决在写代码过程中遇到的代码设计问题.
3.设计模式的六大原则
实体功能独立,多实现接口,增强扩展性
1.开闭原则:
对扩展开放,对修改关闭.尽可能对代码少修改.
2.里式替换原则:
任何父类(基类)出现的地方,子类都可以出现,也就是子类可以替换父类的任何功能(体现了父类的可扩展性)
3.依赖倒转原则:
尽可能面向接口编程,依赖接口而不依赖类,依赖于抽象而不依赖于具体
4.接口隔离原则
一个类如果能实现多个接口,尽可能实现多个,从而降低依赖,降低耦合.
5.最少知道原则
一个实体尽可能少的与其他实体产生相互关联关系,将实体的功能独立
6.合成复用原则
尽量使用合成,聚合的方式,而不使用继承(类似依赖倒转原则)
4.设计模式的分类
总体来说设计模式分为三大类:
1.创建型模式(5个)
单例模式,工厂方法模式,抽象工厂模式,建造者模式
2.结构型模式(7个)
适配器模式,装饰模式,代理模式,外观模式,桥接模式,组合模式,享元模式
3.行为型模式(11个)
策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,状态模式,访问者模式,中介模式,解释器模式,备忘录模式
其实还有两类:并发型模式和线程池模式
/**设计模式参考:
file:///Users/yanjiamin/Desktop/Java/ppt和代码/Java设计模式/Java开发中的23种设计模式详解(转)%20-%20maowang%20-%20博客园.htm
**/
5.常用设计模式
1.单例模式
是创建对象的一种特殊方式,创建一个 类对象后,程序从始至终使用的都是同一个 类对象叫单例(单实例).
在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在
单例模式有3个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销.
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力.
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了.(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程.
按创建对象方式不同可分为两类:
1.懒汉式单例:在使用时创建一个对象
2.饿汉式单例:在类加载时创建一个对象
1.懒汉式单例
1.定义一个空的静态类引用变量(属性)
2.将构造器私有化
3.创建该类的对象并提供一个静态的方法返回
/**
* @Description:懒汉式单例
* @author yanjiamin
* @date 2020年10月13日 上午10:17:25
*/
public class Person {
//1.私有静态属性实例 防止其他类直接引用该成员 此处赋值为null,目的是实现延迟加载
private static Person person=null;
//2.将构造器私有化 防止被实例化
private Person (){
}
//3.提供一个静态的方法,并可返回该类的对象 静态工程方法,创建实例
public static Person getInstance(){
if(person==null){
// 第一次访问
person = new Person();
}
return person;
}
public void play() {
System.out.println("Person===玩.....");
}
}
2.饿汉式单例
1.创建一个类的静态对象
2.将构造器私有化
3.提供一个静态的方法返回该类的对象
public class Student {
//1.在类加载时创建一个对象
private static Student student = new Student();
// 2.构造器私有化
private Student(){
}
// 3.提供返回类对象的静态方法
public static Student getInstance(){
if(student !=null){
return student;
}
return null;
}
}
测试:
public class Test {
public static void main(String[] args) {
//多例模式 每一次创建得到的是不同的对象
Animal an1=new Animal();
Animal an2=new Animal();
an1.play();
System.out.println(an1);
an2.play();
System.out.println(an2);
//单例模式
//懒汉式单例
Person p1=Person.getInstance();
Person p2=Person.getInstance();
p1.play();
System.out.println(p1);
p2.play();
System.out.println(p2);
//Person p3=new Person();构造器私有化了,不能随意创建Person对象
//饿汉式单例
Student s1=Student.getStudent();
Student s2=Student.getStudent();
s1.play();
System.out.println(s1);
s2.play();
System.out.println(s2);
}
}
2.工厂方法模式
创建对象的过程不再由当前类实例化,而是由工厂类完成,在工厂类中只需要告知对象类型即可.工厂模式中必须依赖接口.(比如生产电脑,自己生产相当复杂,转而交给专业的工厂代为生产)
1.普通工厂模式
就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建
以生产“电脑”为例,电脑有办公的功能,可以生产一体机或者笔记本
* @Description:
* 生产电脑的工厂
*先创建工厂再生产电脑
* @author yanjiamin
* @date 2020年10月13日 上午11:17:37
*/
public class ComputerFactory1{
public Computer produce(String type) {
Computer computer=null;
if (type.equals("personalComputer")) {
computer=new PersonalComputer();
}else if (type.equals("workComputer")) {
computer=new WorkComputer();
}else {
System.out.println("不能生产");
}
return computer;
}
}
2.多个工厂方法模式
是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象
以生产汽车为例,不同品牌的汽车有不同的生产工厂
public interface Car {
public void showInfo();
}
public class AudiCar implements Car {
@Override
public void showInfo() {
System.out.println("这是一台奥迪汽车。。");
}
}
public class BMWCar implements Car {
@Override
public void showInfo() {
System.out.println("这是一台宝马汽车。");
}
}
/**
生产汽车的工厂接口
**/
public interface CarFactory {
public Car produce();
}
public class AudiCarFactory implements CarFactory {
@Override
public Car produce() {
return new AudiCar();// 这里AudiCar是Car的实现类
}
}
public class BMWCarFactory implements CarFactory {
@Override
public Car produce() {
return new BMWCar();// 因为BWMCar是Car的实现类
}
}
public class Test1 {
public static void main(String[] args) {
//先创建 汽车工厂
CarFactory bmwFactory = new BMWCarFactory();
// 这个工厂生产的汽车就是 宝马
Car bmw = bmwFactory.produce();
bmw.showInfo();
//这个模式对于同一级别的产品,可扩展性高
//可以扩展不同品牌的汽车,此时不需要修改代码,只需要增加代码即可
// 创建一个新的品牌汽车 大众汽车
CarFactory dazhongFactory = new DazhongCarFactory();
Car car = dazhongFactory.produce();
car.showInfo();
}
}
3.静态工厂模式
将工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可
/**
* @Description:静态工厂方法模式
* 不用创建工厂,直接生产,节约资源,缺点是一旦创建一直存在
*找已经建好的工厂生产电脑
* @author yanjiamin
* @date 2020年10月13日 上午11:34:15
*/
public class ComputerFactory2 {
public static Computer produce(String type) {
Computer computer=null;
if (type.equals("personalComputer")) {
computer=new PersonalComputer();
}else if (type.equals("workComputer")) {
computer=new WorkComputer();
}else {
System.out.println("不能生产");
}
return computer;
}
}
测试:
public class Test {
public static void main(String[] args) {
//简单工厂方法模式
//先创建工厂(创建工厂对象)
ComputerFactory1 factory=new ComputerFactory1();//通过工厂类创建对象
//再让工厂生产电脑(创建电脑对象)
Computer computer1=factory.produce("personalComputer");
computer1.work();
Computer computer2=factory.produce("workComputer");
computer2.work();
//静态方法工厂模式
//直接找工厂生产电脑
Computer computer=ComputerFactory2.produce("personalComputer");
computer.work();
}
}
总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式
3.抽象工厂模式
工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,拓展性较好.
对于在工厂方法的基础上,对同一个品牌的产品有不同的分类,并对分类产品创建的过程
比如:一个汽车产品 会分为不同的种类(比如:迷你汽车 , SUV汽车 )
/**
*mini汽车接口
**/
public interface MiniCar {
public void showInfo();
}
public class BMMiniCar implements MiniCar {
@Override
public void showInfo() {
System.out.println("这是宝马 mini汽车....");
}
}
public class ADMiniCar implements MiniCar{
@Override
public void showInfo() {
System.out.println("这是奥迪 mini汽车....");
}
}
/**
*SUV汽车接口
**/
public interface SUVCar {
public void showInfo();
}
public class BMSUVCar implements SUVCar{
@Override
public void showInfo() {
System.out.println("这是宝马SUV汽车.....");
}
}
public class ADSUVCar implements SUVCar{
@Override
public void showInfo() {
System.out.println("这是奥迪SUV汽车......");
}
}
public interface CarFactory {//汽车生产工厂 可以生产两种型号的汽车 两条产品线
//不同品牌的两种型号汽车
public MiniCar produceMiniCar() ;
public SUVCar produceSUVCar() ;
}
public class BMCarFactory implements CarFactory{
@Override
public MiniCar produceMiniCar() {
return new BMMiniCar();
}
@Override
public SUVCar produceSUVCar() {
return new BMSUVCar();
}
}
public class ADCarFactory implements CarFactory{//相同类型继承 不同类型实现;
// 一类事物是否定义为接口,看该类事物是否需要分类即扩展
@Override
public MiniCar produceMiniCar() {
return new ADMiniCar();
}
@Override
public SUVCar produceSUVCar() {
return new ADSUVCar();
}
}
package abstractfactorymode;
/**
* @Description:测试
* @author yanjiamin
* @date 2020年10月13日 下午3:52:18
*/
public class TestCar {
public static void main(String[] args) {
CarFactory carFactory=new ADCarFactory();
MiniCar car =carFactory.produceMiniCar();
car.showInfo();
//生产大众SUV汽车
//创建 生产大众SUV汽车的工厂
CarFactory carfactory=new DaZhongSUVCarFactory();
//生产汽车
SUVCar car2=carfactory.produceSUVCar();
car2.showInfo();
}
}
总结:普通工厂模式, 工厂方法模式和抽象工厂模式的区别和用途
1.对于简单工厂模式(包括静态和非静态),用于生产同一结构中的任意产品,对于新增产品不适用.(比如:生产电脑,不能再生产其它如汽车产品)
2.对于工厂方法模式,在简单工厂模式的基础上,生产同一个等级结构中的固定产品,支持新增产品(比如:生产不同品牌的电脑,支持新增品牌)
3.对于抽象工厂模式,用于生产拥有相同类型(Mini,SUV)的不同种类(品牌),支持新增种类,不支持新增类型(比如:生产不同品牌的相同类型的电脑,支持新增拥有相同类型的品牌)
4.模版方法
定义
模版方法是一种行为模式,父类的一个方法定义:完成这个行为的步骤,但不具体实现细节,由子类完成各个步骤的实现.在创建子类对象时,最终的实现过程是取决于子类实现.(不同对象完成某一件事的表现不同)
模板方法的准备:
1、继承关系
2、父类是抽象类(AbstractClass) :抽象类实现了模板方法,定义了算法的骨架
3、子类继承抽象类(ConcreteClass):实现抽象方法,完成完整的算法
以早上去学校举例,老师和学生的状态不一样
public abstract class AbstractPerson {
/**
* 在抽象类中定义一个模版方法,是实现这个方法的基本骨架
* 每一步骤由子类具体实现
*/
public void preparedSchool(){//模版方法:完成早上去学校这一行为的步骤
getUp();
dressing();
eat();
}
//起床
public abstract void getUp();
//穿衣服
public abstract void dressing();
//吃早餐
public abstract void eat();
}
public class Student extends AbstractPerson {
@Override
public void getUp() {
System.out.println("学生起床了");
}
@Override
public void dressing() {
System.out.println("学生开始穿衣服了");
}
@Override
public void eat() {
System.out.println("学生开始吃早餐");
}
}
public class Teacher extends AbstractPerson {
@Override
public void getUp() {
System.out.println("老师起床,7点半起床");
}
@Override
public void dressing() {
System.out.println("老师要衣服得体,穿工装");
}
@Override
public void eat() {
System.out.println("老师吃早餐。");
}
}
package templatemethod;
/**
* @Description:测试
* @author yanjiamin
* @date 2020年10月13日 下午6:16:46
*/
public class Test {
public static void main(String[] args) {
Student stu = new Student();
stu.preparedSchool();
Teacher teacher = new Teacher();
teacher.preparedSchool();
}
}
二.内部类(inner class)
1.定义
在一个类中定义另一个类的代码结构,定义在类内部的类通常称为“内部类”,外面的类称为“外部类”,在逻辑关系上,内部类与外部类是从属关系,比如:一个People类中包含收货地址类(收货人,收货联系方式,…)
2.分类
2.1 普通内部类
一个类A中定义另一个类B,其中类B就是类A的内部类,也是类A的一部分
总结:
1.外部类的方法中,可以直接访问内部类的所有成员(包括私有)
2.内部类的方法中,也可以直接方法外部类的所有成员,当外部和内部的成员名相同时,就近原则访问成员,或者引入外部类的对象来访问外部类成员
2.2 静态内部类
在普通内部类基础上,增加“static”关键字,与静态方法相似,满足静态的要求
总结:
1.在静态内部类的方法中,对于静态内部类中的静态方法可以直接通过 静态内部类类名.静态方法名 调用
2.在静态内部类的方法中,对于静态内部类中的非静态方法,需要创建静态内部类的对象才能访问
2.3 方法内部类
在一个方法中定义的类,其中这个类只属于该方法,也只能在该方法中使用
注意:内部类生成的class文件 命名格式: 外部类名$内部类名.class
总结:
1.方法内部类中 可以直接使用外部类的成员
2.存在方法内部类的方法可以调用方法内部类里面的方法
public class People {
private String pname="张三";
int age=18;
public void sayHello() {
System.out.println("Let us say Hello");
//外部类的方法中可以使用内部类的所有属性和方法
Address address=new Address();
address.addressName="湖北武汉";
address.contentName="李四";
address.addressInfo();
}
//1.普通内部类 收货地址类
class Address{
private String addressName;//收货地址
private String contentName;//联系人
int age=20;
public void addressInfo() {
System.out.println("联系人:"+contentName+" 收货地址:"+contentName);
//内部类的方法可以直接访问外部类的属性和方法
System.out.println("可以访问外部类属性:"+pname);
sayHello();
}
public void showAge(People people) {
System.out.println("内部类age:"+age);
System.out.println("内部类age:"+this.age);
System.out.println("外部类age:"+people.age);
}
}
//2.静态内部类 卡信息类
static class Card {
private static String cardNo="42000";
private String cardName="身份证";
//静态方法
public static void cardShowInfo1() {
System.out.println("静态内部类1"+cardNo);
}
//非静态方法
public void cardShowInfo2() {
System.out.println("静态内部类2"+cardName);
}
public void method1() {
// 对于静态方法可以直接类名.方法名
Card.cardShowInfo1();
// 对于非静态方法,需要创建Card类的对象访问
Card card = new Card();
card.cardShowInfo2();
}
}
//3.方法内部类
public void method3(){
int score = 98;
// 在这里定义一个类
class MyClass{
String subject="Java";
public void getSubjectScore(){
//方法内部类中 也可以使用外部类的成员
sayHello();
System.out.println(pname+"的"+subject+":"+score);
}
}
//调用方法内部类里面的方法
MyClass mycls = new MyClass();
// mycls.subject;
mycls.getSubjectScore();
}
}
测试:
public class TestInnerClass {
public static void main(String[] args) {
//1.普通内部类
//创建外部类对象
People people=new People();
//创建内部类对象 必须依赖外部类对象
People.Address address=people.new Address();
//address不能访问私有属性
address.addressInfo();
address.showAge(people);
//2.静态内部类
People.Card.cardShowInfo1();
//创建静态内部类对象
People.Card card=new People.Card();
card.cardShowInfo2();
// 3 .方法内部类
//调用方法
people.method3();
2.4 匿名内部类:
定义一个没有类名,只有对方法的具体实现的类.通常它依赖于实现关系(接口)或继承关系(父类)(匿名实现或者继承)
a、基于实现关系
public interface MyInterface {
// 学习
public void study();
// 工作
public void work();
}
// 创建一个匿名类(让接口的引用 指向匿名类的对象)
MyInterface person = new MyInterface() {
@Override
public void study() {
System.out.println("这个人也好好学习");
}
@Override
public void work() {
System.out.println("这个人也好好工作");
}
};
person.study();
person.work();
b、基于继承关系
public class MyClass {
public void service(){
System.out.println("提供服务的方法。");
}
}
// 父类 new 一个 匿名类,这个匿名类是它的子类
MyClass cls = new MyClass(){
@Override //匿名类重写父类的方法 service
public void service() {
System.out.println("这是子类的方法");
}
};
cls.service();
三.异常
1.异常的概述
异常定义:程序在执行过程中,由于发生"不正常"事件,导致JVM非正常中断,使程序无法正常运行,称为异常.
生活中的异常:早上起床去上课,平时骑车20分钟可以到达教室,由于天气原因导致不能按时到达教室上课,此时就属于异常现象.
2.异常关键字
try: 试一试 ,将可能发生异常的代码使用try包裹 ,try和catch不能单独出现
catch : 捕获异常, 当发生指定的异常对象时,执行catch代码
finally:无论是否发生异常,都会执行这个语句块,异常之后的最终处理 ,不常用,多用于资源回收
throw:抛出异常
throws:声明异常
3.捕获异常和层次关系
捕获异常:当程序在运行时发生了异常,为了让程序正常执行,需要对异常捕获(catch),此过程称为捕获异常.
Java是面向对象语言,异常本身是一个类(Exception),当发生异常时就会创建异常对象,捕获的就是异常对象.
//1.发生异常后正确捕获异常 一个try+一个catch
System.out.println("请输入一个数字");
Scanner sc=new Scanner(System.in);
//异常代码可能发生异常,当用户输入的是非数字时,会抛出异常对象
try {//发生异常后,try里面的异常代码后面的代码不会执行
System.out.println("try里面的代码");
int n=sc.nextInt();//InputMismatchException:由于未知事件即输入不规范(当用户输入非数字时),可能会出现异常,需要进行处理
if (n%2==0) {
System.out.println(n+"是一个偶数");
}
} catch (Exception ee) {//捕获父类异常对象:发生的什么异常就捕获对应的异常对象,不能确定异常类时,可以使用父类Exception异常类
System.out.println("输入不规范");//直接使用Exception类的缺点:异常不清晰
}
System.out.println("程序继续运行直到结束。。。。");
// 2.抛出的异常 不能被一个catch正确捕获, 使用 一个try + 多个catch 格式
try {
int[] num = {1, 2, 3};
System.out.println(num[1]); // 没有捕获该异常对象,JVM依然终止运行
System.out.println(10/0);
}catch(NullPointerException ee){
System.out.println("这是空指针异常");
}catch(ArrayIndexOutOfBoundsException ee){
System.out.println("数组下标越界异常");
}catch(Exception ee){
// 输出异常 堆栈消息 方便程序员排错(尽可能避免用户看见)
ee.printStackTrace();
System.out.println("系统繁忙!"+ee.getMessage());
}
System.out.println("程序结束");
//3.try...finally结构
try{//捕获异常 但异常代码后面的语句块不会执行
System.out.println("请输入两个数 ,计算两个数相除");
Scanner sc = new Scanner(System.in);
int num1 = sc.nextInt();
int num2 = sc.nextInt();
double s = num1/num2; // 可能出错
System.out.println(" try里面结束,结果:"+s);
}finally{
System.out.println("无论是否发生异常,都会执行这个语句块,一般用于资源回收");
}
//try...catch...finally结构
try {
System.out.println("请输入两个数 ,计算两个数相除");
Scanner sc = new Scanner(System.in);
int num1 = sc.nextInt();
int num2 = sc.nextInt();
double s = num1 / num2; // 可能出错
System.out.println(" try里面结束,结果:" + s);
}catch(ArithmeticException ee){
ee.printStackTrace();
System.out.println("除数不能为0 !!");
}catch(Exception ee){
ee.printStackTrace();
System.out.println("系统繁忙!!!");
}finally {
System.out.println("用于资源回收。");
}
4.抛出异常
抛出异常时,底层可以往上层抛出异常,但是到了异常继承关系的最顶层不能再抛出,必须处理异常即对异常进行系统封装处理.
抛出异常的代码的后面的代码不会再执行.
/**
* 根据下标访问数组元素
* @param array
* @param index
* @return
*/
public static int getEleByIndex(int [] array , int index){
// 抛出异常: 可以在异常发生时 或发生之前 创建一个异常对象并抛出
// 手动抛出一个异常 throw new 异常类([异常消息]);
if(index <0 || index > array.length-1){
//抛出异常
throw new ArrayIndexOutOfBoundsException("你的下标越界了");
}
int n = array[index];
return n;
}
public static void main(String[] args) {
//数组
int [] array = {2,1,4,5};
int index=4;
// 定义方法访问下标的元素 此时会产生异常 并抛出给方法的调用者
try {
int num = getEleByIndex(array, index);
System.out.println("访问的元素:" + num);
}catch(ArrayIndexOutOfBoundsException ee){
System.out.println(ee.getMessage());
}
System.out.println("结束。。。");
}
5.异常分类
由于有些异常是不能直接抛出的 ,需要先声明才可以抛出.将异常分为两大类:
1、 编译期异常(check 异常或者检查异常):在编译期间检查异常,如果没有处理异常,则编译出错
对于编译期异常,要么try…catch…finally处理异常,要么通过throw关键字向上抛出异常同时调用者使用throws关键字声明要抛出的异常
//创建一个文件类的对象
File file = new File("d:/aaa.txt");
// 在写代码(编译之前)时 一定要处理的异常(try..catch 或者 throws),就是编译时异常
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
//这里的IOException 就是 编译期异常,需要手动处理的
2、运行期异常(runtime 异常或者运行异常):在运行期间检查异常,编译期不被检测
对于运行期异常,要么try…catch…finally处理异常,要么通过throw关键字向上抛出异常
// 在运行期间抛出异常 不需要事先处理的 NullPointException是运行异常
String str=null;
System.out.println(str.length());
Exception中常用的异常类
1.检查异常(check Exception)
IOException :IO操作
FileNotFoundException: 文件未找到异常
SQLException:
EOFException:读写文件尾异常
DateFormatException:日期格式化异常
SocketException:SocketException
- 运行异常(RuntimeException)
ArrayIndexOutOfBoundsException :数组下标越界异常
NullPointerException:空指针异常
ArithmeticException: 算术异常
NumberFormatException :数字格式化异常
ClassNotFoundException: 类没找到异常
ClassCaseException: 类转换异常
注意: 对于抛出检查异常,需要使用throws声明,对于抛出运行时异常,不需要使用throws声明
系统抛出异常或者自定义抛出异常,处理或者继续抛出异常给调用者.抛出的异常可以作为消息提示机制
6.自定义异常
1、为什么需要使用自定义异常
在Java中每一个异常类都表示特定的异常类型, 例如 NullPointerException表示空指针 ArithmeticException表示算术异常, 但是sun公司提供的API中不可能将实际项目中的业务问题全部定义为已知的异常类 ,这就需要程序员根据业务需求来定制异常类,例如 用户注册,可以定义用户注册异常(RegisterException),分数不能为负数也可以定制异常(ScoreExcecption).
2、什么是自定义异常
在开发中根据自己的业务情况来定义异常类 ,灵活性较高,且方便易用。
3、如何实现自定义异常
a、定义编译期异常类,创建一个类继承 java.lang.Exception ;
b、定义运行期异常类,创建一个类继承java.lang.RuntimeException;
4、案例分析:自定义异常应用
要求: 模拟用户注册操作, 用户输入用户名 ,验证用户名是否存在,如果存在,则抛出一个异常消息 “亲,该用户已存在,不能注册” ,通过自定义异常提示消息
public class RegisterException extends Exception {
public RegisterException(){
}
public RegisterException(String message){
// 将message(可作为提示/反馈信息) 赋值给父类的构造器
super(message); // 将message赋值给父类的 属性,可通过getMessage()方法获取
}
}
public class TestRegister {
// 模拟已存在的用户
String [] users = {"袁魏巍","王麻子","王小花//全局
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要注册的用户:");
String uname = sc.next();
TestRegister obj = new TestRegister();//创建异常对象
try {
// 调用方法
obj.checkUserName(uname);//用户存在时抛出异常即执行catch语句块
System.out.println("注册成功");
} catch (RegisterException e) {
System.out.println("注册失败");
System.out.println(e.getMessage());
}
}
/**
* 检查用户是否存在
* @param username
* @return true 表示通过
* 异常表示不通过
*/
public boolean checkUserName(String username) throws RegisterException{
// 使用foreach遍历
/**
* for(数据类型 变量名 : 数组名/集合名 ){
* 循环中的 变量名代表的就是数组的元素
* }
*/
for(String u : users){
// 判断u是否与 username相等 ,相等说明用户存在,需要抛出异常
if(u.equals(username)){
throw new RegisterException("亲,"+username+" 已存在,不能注册");//抛出异常 且后面的代码不会执行
}
}
return true;
}
}