目录
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("错误的相加操作");
}
}
}