【JavaSE】之单例模式与异常体系

目录

1.包的定义及使用、访问控制权限

2.单例设计模式与多例设计模式

3.Java异常与捕获

1.包的定义及使用

1.1包的本质实际上就是文件夹

定义用:package

package www.bit.java;

一旦程序出现包名称,那么*.class必须存在相应目录下。在JDK编译的时候使用配置参数。

打开包编译命令:javac -d . 类名.java

-d表示生成目录,根据package定义生成

“.”:表示当前所在目录生成子目录

        按照此种方式编译完成后就会发现,自动会在当前目录下生成相应的文件夹以及相应的*.class文件。一旦程序类上出现了包名称,那么在执行的时候就需要带上包名称,即使用完整类名称“包.类”。

java www.bit.java.类名

1.2包的导入(import)

例:编写简单Java类,本类需要被其他程序类所使用

package www.bit.java.util;

public class Message {
    public void print(){
        System.out.println("Hello world");
    }
}

导入包:

package www.bit.java;
import www.bit.java.util.Message;

public class Test2{
    public static void main(String[] args){
        Message message = new Message();
        message.print();
    }
}

         从正常的角度看,Test2类引用的Message类,那么首先编译的应该是Message类,而后才是Test类。那如果在引用多个包的情况下就得编译多个类,所以最好的方法是让java自己去匹配编译顺序,最常用的打包编译命令是:

javac -d . ./*.java

注意:类使用class和public class的区别:

1.public class:文件名称必须与类名称保持一致,如果希望一个类被其他包访问,则必须定义为public class

2.class:文件名称可以与类名称不一致,在一个*.java中可以定义多个class,但是这个类不允许被其他包所访问。

1.3系统常用包

1.3.1 java.long:系统常用基础类(String、Object、包装类),JDK1.1之后自动导入

1.3.2 java.util:Java提供的工具程序包(集合类、ArrayList 、HashMap),需要手工导入

1.3.3 juc:java.util.concurrent:并发程序包

1.4访问控制权限

private < default (包访问权限,仅供在同一包下访问) < protected(继承访问权限,仅供子类使用) < public

例:观察protected访问权限

package father;
public class Father {
    // 此时定义的是protected权限
    protected String msg = "www.bit.java" ;
}

定义另外一个包进行该类继承

package child;
import father.Father; // 不同包

public class Child extends Father{
    public void print() {
        System.out.println(super.msg); // 父类中protected权限
    }
}

定义测试类

package test;
import child.Child;

public class TestProtected {
    public static void main(String[] args) {
        Child child = new Child() ;
        child.print();
    }
}

在不同包中,只有子类能访问父类中的protected权限。

2.单例设计模式与多例设计模式

2.1单例设计模式

定义:一个类只允许产生一个实例化对象

a.对象如何产生? 通过类的构造方法

b.怎么限制对象的产生? 通过构造方法限制

饿汉式单例:上来就new

特点:不管是否使用Singleton类的对象,只要类加载了,那么一定会自动创建好一个公共的SINGLETON对象。

//饿汉式单例
class Singleton{
    //类内部产生实例化对象,只在类加载的时候产生一个
    //声明成常量,因为不会再改变,要改变就是将SINGLETON的地址改变,但是在外部改变不了
    private static final Singleton SINGLETON = new Singleton();
    //构造方法私有化,类外部无法产生实例化对象
    private Singleton(){}
    //通过类名调用
    public static Singleton getSingleton(){
       return SINGLETON;
    }
    public void test(){
        System.out.println(this);
    }
}
public class Test {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getSingleton();
        Singleton singleton1 = Singleton.getSingleton();
        singleton.test();
        singleton1.test();
    }
}

懒汉式单例:用时在new(双重加锁单例模式),可能会出现线程安全问题

特点:当第一次去使用Singleton对象的时候才会为其产生实例化对象的操作

//懒汉式单例
class Singleton{
       //类内部产生实例化对象
    private static Singleton SINGLETON;
       //构造方法私有化,类外部无法产生实例化对象
    private Singleton(){}
       //通过类名调用
    public static Singleton getSingleton(){
        if(SINGLETON == null){
           SINGLETON = new Singleton();
        }
        return SINGLETON;
    }
    public void test(){
        System.out.println(this);
    }
}
public class Test {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getSingleton();
        Singleton singleton1 = Singleton.getSingleton();
        singleton.test();
        singleton1.test();
    }
}

总结单例模式特点:

  • 构造方法私有化,来控制对象的个数
  • 类的内部提供一个对象,并且是静态属性
  • 提供一个静态方法,将对象返回

2.2多例模式-有限个数对象

所谓的多例只是比单例多了一些实例化对象而已

//描述性别类
class Sex{
    private String title;
    public static final int MALE_FLAG = 1;
    public static final int FEMALE_FLAG = 2;
    private static final Sex MALE = new Sex("男");
    private static final Sex FEMALE = new Sex("女");
    private Sex(String title){
        this.title = title;
    }
    public static Sex getInstance(int flag){
        switch(flag){
            case MALE_FLAG:
                return MALE;
            case FEMALE_FLAG:
                return FEMALE;
            default:
                return MALE;
        }
    }

    @Override
    public String toString() {
        return this.title;
    }
}

public class Test{
    public static void main(String[] args) {
        Sex male = Sex.getInstance(Sex.MALE_FLAG);
        Sex female = Sex.getInstance(Sex.FEMALE_FLAG);
        System.out.println(male);
        System.out.println(female);
    }
}

不管多例还是单例都有共同的特点:

1.构造方法私有化

2.类内部一定会提供一个static方法用于取得实例化对象。

3.Java异常与捕获

我们先来看一下异常的继承类结构:

Error(栈溢出异常):Error类描述Java运行时内部错误与资源耗尽错误。应用程序不抛出此类异常,这种内部错误一旦出现,除了告知用户并使程序安全终止以外,别无他法。

以Error结尾的类为自己及其子类。

例:

public class Test{
    public static void main(String[] args) {
        digui(10);
    }
    public static int digui(int num){
        return digui(num);
    }
}

RuntimeException(运行时异常):由于程序错误导致的异常。

IOException:程序本身没有问题,但由于出现I/O问题导致的异常(例如:打开一个并不存在的文件)

非受查异常:继承于Error与RuntimeException类的所有异常子类称为非受查异常(不强制用户进行异常处理)

受查异常:Exception以及IOException子类属于受查异常(强制用户进行异常处理)

例:产生异常

public class Test{
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前...");
        System.out.println("2.数学计算中"+(10/0));
        System.out.println("3.数学计算完成");
    }
}

程序之中产生异常后,异常语句产生之前的语句可以正常执行完毕,而异常产生之后程序直接进行了结束。为了保证程序出现异常后还可以继续向下执行,就需要进行异常处理。

3.1异常处理格式

为了保证程序出现异常后也能正常执行下去,需要进行异常处理

语法如下:

try{
    //有可能出现异常的语句
}[catch(异常类    对象)......]{
    //出现异常后的解决方案
}[finally]{
    //异常出口,无论是否产生异常,均会执行finally代码块
    //即便try、catch中存在return 语句,也会在return之前执行finally代码块,执行的是finally的return语句,但是如果finally不存在return语句,该走哪个return就走哪个return
}

对于三个关键字,还可以出现的三种组合:

try...catch...

try...finally...

try...catch...finally...

例:对异常进行处理 

public class Test{
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前...");
        try {
            System.out.println("2.数学计算中"+(10/0));
        } catch (ArithmeticException e) {
            System.out.println("出现异常,除数有误");
        }finally {
            System.out.println("4.finally代码块无论如何都会执行");
        }
        System.out.println("3.数学计算完成");
    }
}

例:即便try、catch中存在return 语句,也会在return之前执行finally代码块,执行的是finally的return语句,但是如果finally不存在return语句,该走哪个return就走哪个return 

public class Test{
    public static void main(String[] args) {
        System.out.println(test(0));
    }
    public static int test(int num){
        try {
            System.out.println(10/num);
            System.out.println("1.***********");
            return 1;
        } catch (Exception e) {
            System.out.println("2.###########");
            return 2;
        }finally {
            System.out.println("3.$$$$$$$$$$$");
            return 3;
        }
    }
}

 

public class Test{
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前...");
        try {
            int num1 = Integer.parseInt(args[0]);
            int num2 = Integer.parseInt(args[1]);
            System.out.println("2.数学计算中"+(10/0));
        } catch (ArithmeticException e) {
            System.out.println("出现异常,除数有误");
        }
        System.out.println("3.数学计算完成");
    }
}

 

通过以上代码发现,通过catch捕获异常的时候如果没有捕获指定异常,程序依然无法进行处理 。如果使用多个catch块,那么我们就得清楚程序中可能出现的异常。

例:直接捕获父类异常

public class Test1{
    public static void main(String[] args) {
        System.out.println("1.数学计算开始前...");
        try {
            int num1 = Integer.parseInt(args[0]);
            int num2 = Integer.parseInt(args[1]);
            System.out.println("2.数学计算中"+(10/0));
        } catch (RuntimeException e) {  //直接向上转型
            e.printStackTrace();  //打印错误堆栈
        }
        System.out.println("3.数学计算完成");
    }
}

3.2throws-用在方法上,明确表示此方法可能会产生异常但是方法内部不处理,将异常抛回给调用处

如果用throws将异常扔回的话,产生异常的语句以后的代码将不再执行,因为此时已经不再此方法上。

例:使用throws定义方法

public class Test2{
    public static void main(String[] args){
        try {
            System.out.println(div(10, 0));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static int div(int x, int y) throws Exception{
        return x/y;
    }
}

主方法本身也属于一个方法,所以主方法上也可以使用throws进行异常抛出,这个时候如果产生异常就会交给JVM处理。

例:主方法抛出异常

public class Test2{
    public static void main(String[] args) throws Exception {
        System.out.println(div(10, 0));
    }
    public static int div(int x, int y) throws Exception{
        return x/y;
    }
}

3.3throw-用在方法中。由用户产生异常类而非JVM产生。一般与自定义异常类搭配使用。

例:使用throw产生异常类对象

public class Test2{
    public static void main(String[] args) throws Exception {
        try {
            throw new Exception("抛个异常玩玩");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

throw和throws的区别:

1.throw用于方法内部,主要表示手工异常抛出

2.throws主要在方法声明上使用,明确告诉用户本方法可能产生异常,同时该方法可能不处理此异常。

解释Exception与RuntimeException的区别:

1.使用Exception是RuntimeException的父类,使用Exception定义的异常都要求必须使用异常处理,而使用RuntimeException定义的异常可以由用户选择性的来进行异常处理。

2.常见的RuntimeException:ClassCastException(类型转换异常)、NullPointerException(空指针异常)等。

3.4自定义异常类

例:在进行加法运算时,如果发现两个数相加内容为50,那么就应当抛出一个异常。这种异常Java不会提供,所以就必须定义一个属于自己的异常类。

自定义异常类可以继承两种父类:Exception、RuntimeException。

class AddException extends Exception{
    public AddException(String msg){
        super(msg);
    }
}
public class Test2{
    public static void main(String[] args) throws Exception {
        int num1 = 20;
        int num2 = 30;
        if(num1 + num2 == 50){
            throw new AddException("错误的相加操作");
        }
    }
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gx1500291

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值