学习笔记1-常用类与异常处理


JDK常见包

 java.lang ——包含一些Java语言的核心类,如StringMathIntegerSystemExceptionThread,提供常用功能。在java.lang包中还有一个子包:java.lang.reflect用于实现java类的反射机制。这个包是JVM在程序中自动导入的包         

⑵ java.awt —— 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)

⑶ avax.swing——此包用于建立图形用户界面,此包中的组件相对于java.awt包而言是轻量级组件。

  java.applet——包含applet运行所需的一些类。

  java.net——包含与网络相关的类。如SocketURL

  java.io —— 包含能提供多种输入/输出功能的类。

  java.util——包含一些实用工具类,如日期类、集合类。

 JDK中还有很多其他的包,如用于数据库编程的java.sql包,用于编写网络程序的java.rmi(Remote Method Invocation)。另外,javax.*包是对基本包的扩展,包括用于编写GUI程序的javax. swing包,以及用于编写声音程序的javax. sound包等·

 JDK的所有包中的类构成了java类库,或者叫做J2SE APIjava应用程序的编写都依赖于J2SE API

Object

equals()

Ø 仅当被比较的两个引用变量指向同一对象时,equals()方法才返fpl true

Ø 许多Java类都覆盖了这个方法,如java.io.File, .java.util.Date,java.lang.String、包装类等。比较规则为:如果两个对象的类型一致,并且内容一致,则返回true

hashCode():

Ø 返回对象的哈希码值

Ø HashTableHashMap会根据对象的哈希码值来决定它的存放位置

Ø 为了使程序更健壮,在编写Java类时要养成以下编程习惯

q 如果Java类重定义了equals()方法,那么这个类也必须重定义hashCode()方法,并且保证当两个对象用equals()方法比较的结果为true时,这两个对象的hashCode()方法的返回值也相等。

q 如果Java类实现了Comparable接口,那么应重定义compareTo(), equals()hashCode()方法,保证compareTo ()equals()方法采用相同的比较规则来比较两个对象是否相等,并且保证当两个对象用equals()方法比较的结果为true时,这两个对象的hashCade()方法的返回值相等。

toString():

Ø 返回当前对象的字符串表示,格式为“完整类名@对象的十六进制哈希码”

Ø 许多类,如StringStringBuffer和包装类都覆盖了toString()方法,返回具有实际意义的内容

finalize():

Ø 对于一个已经不被任何引用变量引用的对象,当垃圾回收器准备回收该对象所占用的内存时,将自动调用该对象的finalize()方法。

String

Ø String类用来操作字符串,可以把任意对象和数组转化成字符串

Ø String是字符串常量。String的操作都是改变赋值地址而不是改变值操作。

==”与equals的区别:==”对于两个对象的地址值作比较是否相等,Equals 判断两个对象的内容是否相等

String类的方法

1, 获取

1, 获取字符串的长度:length();

2, 指定位置的字符。Char charAt(int index);

3, 获取指定字符的位置。索引不存在返回-1,所以通过返回值-1来判断一个字符在不在的情况。

int indexOf(int ch);int indexOf(int ch,int fromIndex);

int indexOf(String str);int indexOf(String str,int fromIndex);

int lastIndexOf(int ch);int lastIndexOf(int ch,int fromIndex);

int lastIndexOf(String str);int lastIndexOf(String str,int fromIndex);

4,获取子串。

String substring(int start);//start位开始,到length()-1为止。

String substring(int start,int end);//start开始到end为止。//包含start不包含end

获取整串 substring(0,str.length());

2,判断

1, 字符串中包含指定的字符串吗?Booleancontains(String substring);

2, 字符串是否以指定字符串开头?BooleanstartsWith(string);

3, 字符串是否以指定字符串结尾啊?boolean endsWith(string);

4, 判断字符串是否相同boolean equals(string);覆盖了Object中的方法,判断字符串内容是否相同。

5, 判断字符串内容是否相同,忽略大小写。boolean equalsIgnoreCase(string):

转换

1,通过构造函数可以将字符数组或者字节数组转成字符串。

2,可以通过字符串中的静态方法,将字符数组转成字符串。

static String copyValueOf(char[] );static String copyValueOf(char[],int offset,int count);

static String valueOf(char[]);static String valueOf(char[],int offset,int count);

3,将基本数据类型或者对象转成字符串。

static String valueOf(char);

static String valueOf(boolean);

static String valueOf(double);

static String valueOf(float);

static String valueOf(int);

static String valueOf(long);

static String valueOf(Object);

4,将字符串转成大小写。

String toLowerCase();String toUpperCase();

5,将字符串转成数组。

转成字符数组。char[] toCharArray();

转成字节数组。byte[] getBytes();//可以加入编码表。

6,将字符串转成字符串数组。切割方法。String[] split(分割的规则-字符串);

7,将字符串进行内容替换。变成新字符串。

String replace(oldChar,newChar);

String replace(oldstring,newstring);

8,对字符串进行追加。String concat(string);

String s = new String(a)String s = a;的区别

JavaString类型提供了缓冲池机制,当使用双引号定义对象时,java环境首先去字符串常量池中寻找相同内容的字符串,如存在就直接拿来应用,如不存在则创建一个新字符串放入常量池。

String a=tom;

String b=tom;

上述代码中,变量ab使用的是字符串常量池中同一个存储对象

当使用构造函数定义对象时,每次调用都会创建一个新对象。

//创建了二个“对象”,一个由jvm隐含地创建,放入字符串常量池里,还有一个通过new语句显式创建,在堆里

String a= new String(tom);

String b=new String(tom);

上述代码中,变量ab使用的是两个不同的存储对象,只是对象中的内容相同。

正则表达式

 

 

StringBuffer

1,添加。

StringBuffer append(data):在缓冲区中追加数据。追加到尾部。

StringBuffer insert(index,data):在指定位置插入数据。

2,删除。

StringBuffer delete(start,end);

StringBuffer deleteCharAt(index);

3,修改。

StringBuffer replace(start,end,string);

void setCharAt(index,char);

void setLength(len);

4,查找。

int indexOf(string);

int indexOf(string,int fromIndex);

int lastIndexOf(string);

int lastIndexOf(string,int fromIndex);

5,获取子串

string substring(start);

string substring(start,end);

6,反转。

StringBuffer  reverse()

StringStringBufferStringBuilder详解

n String是字符串常量,String在编译后是final的,所以是定长,内容不可变;StringBufferStringBuilder可变。

n 不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了可变版本,即StringBuffer和StringBuilder

n StringBufferJDK1.5以前的,StringBuilder是升级以后的,二者方法都一样,是缓冲区,,容器长度可变。StringBuilder更高效,因为不考虑线程同步Synchronized问题如果需要同步,则使用 StringBuffer

n 因为String对象建立后不能改变,所以对于每一个不同的字符串使用内容相同的字符串,不必每次都new一个String,都需要一个String对象来表示,所以经常对字符串进行修改会引起很大的内存开销。而StringBuffer和StringBuilder可以只修改一个字符串对象,而不每个不同的字符串都要生成一个新的对象。

n String a = "123"a = a + "456"细节;在用String类对象直接+操作时,JVM会创建一个临时的StringBuffer类对象,并调用其append()方法完成字符串的拼接,这是因为String类是不可变的,拼接操作不得不使用StringBuffer类(并且JVM会将"Hello"和" world!"创建为两个新的String对象)。之后,再将这个临时StringBuffer对象转型为一个String,内存开销不菲

n 操作字符串一般使用String。但经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响你需要使用字符串来处理大量数据的时候,建议使StringBuilder而不是String

 

基本数据类型的包装类

Ø 包装类中提供了一系列实用的方法,比如Integer类的静态方法parseInt(String s)能把字符串转换为整数,java集合中不能存放基本类型数据,如果要存放数字,应使用包装类型

Ø 所有的包装类都是final的,因此没有子类。

关于自动装箱与拆箱的小问题:

Integer a = new Integer(127);

Integer b = new Integer(127);

System.out.println(a == b);//false

System.out.println(a.equals(b));//ture

Integer x = 127;

Integer y = 127;

System.out.println(x == y);//ture

System.out.println(x.equals(y));//ture

// JDK1.5后,如果两次自动装箱的int型数值在1个字节范围内( -128127), 那么第二次将不会重新开辟内存空间,而会共享第一次创建空间的值。原因在于在Integer类里有个内部类IntegerCache存放-128127范围内的对应Integer类对象,而该类的静态方法valueOf的实现是当数在 -128127之内时直接返回内部类IntegerCache中存放的对应的Integer类对象,否则new一个新对象。这是设计模式中的享元模式。

MathRandom

java.util.Math

Ø Mathfina类,没有子类。Math类的构造方法是private的,因此Math类不能被实例化。

Ø 包含了所有用于几何和三角的浮点运算方法,这些方法都是静态的 

q abs(X  x):返回不同类型的绝对值。

q max(两个参数):返回两个数中的最大值。

q min(两个参数):返回最小值。

q random():返回大于等于0小于1的随机数。

q pow(double a, double b):ab次幂

q round(double a):四舍五入

q ceil(double a):返回大于A的最小整数。

q floor(double a):返回小于A的最大整数。

java. util.Random

提供了一系列用于生成随机数的方法。

Ø nextInt():返回下一个int类型的随机数,随机数的值大于或等于0

Ø nextInt(int n):返回下一个int类型的随机数,随机数的值大于或等于0且小于参数n

Ø nextLang();返回下一个long类型的随机数,随机数的值位于long类型的取值范围内

Ø nextFioat():返回下一个float类型的随机数,随机数的值大于或等于0且小于1.0

Ø nextDouble():返回下一个double类型的随机数,随机数的值大于或等于0且小于1.0

Ø nextBoolean(}:返回下一个boolean类型的随机数,随机数的值为truefalse

BigDecimal 

Ø 能作用于intfloat的操作,也同样能作用于BigIntegerBigDecimal。只不过必须以方法调用方式取代运算符方式来实现。这样牺牲了速度,但换来了精度。

Ø BigDecimal支持任意精度的整数。在运算中,可以淮确地表示任何大小的整数,而不会丢失任何信息。而BigDecimal支持任何精度的定点数,例如,可以用它进行精确的货币计算。

DateCalendarDateFormat

java.util.Date

Ø 包装了一个long类型数据,表示与19701100:00:00这一刻所相距的毫秒数。Date类用于表示日期和时间

Ø 由于开始设计Date时没有考虑到国际化,所以后来又设计了DateFormat类和Calendar类来解决Date类中的问题

Ø Date类的默认构造方法调用System_currentTimeMillis{)方法获取当前时间,

new Date()语句等价于:new Date(System.currentTimeMillis())

Ø Date.getTime():日期对象转成毫秒值。

setTime():毫秒值转成日期对象。

java. text.DateFormat抽象类

Ø 用于定制日期的格式,它有一个具体子类为java.text.SimpleDateFormat

1, format(Date date):Date格式转化为日期或者时间的字符串

2, DateFormat getDateInstance():获取日期,按照默认的格式。

3, Date parse(String source,ParsePosition pos):根据给定的规则生成日期和时间字符串

4, // 设置日期格式, new Date()为获取当前系统时间

String strTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

.format(new Date());

java.util.Calendar

1, Calendar getInstance():使用静态方法,返回这个类对象

2, Add(int field,int amount):增加或减去指定的时间。

3, Int get(int field):返回给定的字段的值。

4, Set(int year, int month, int date):设置时间

SystemRuntime

Ø Java不支持全局方法和变量,Java设计者将一些系统相关的重要方法和变量收集到了一个统一的类中,这就是System类 

Ø Lang型中System类里面都是静态方法,要使用直接用类名.方法就可以调用了。

  1currentTimeMillis():返回以毫秒为单位的当前时间。

  2exit():终止java虚拟机

  3getProperties():返回Properties确定当前系统属性。

  4setProperty(String key, String value):自定义键值的系统属性。

Ø Runtime类封装了Java命令本身的运行进程,其中的许多方法与System中的方法重复,是单例设计模式

String shell;

if (file.isDirectory()) {

shell = "ls " + file.getCanonicalPath() + " -lad";// 获得当前目录的权限

else {

shell = "ls " + file.getCanonicalPath() + " -l";// 获得当前文件的权限

}

Runtime runtime = Runtime.getRuntime();// 获取runtime对象来执行shell脚本

Process process = runtime.exec(shell); // 执行脚本

InputStream inputStream = process.getInputStream();// 获取脚本执行的结果流

异常

引子:异常情况会改变正常的流程,导致恶劣的后果。为了减少损失,应事先充分预计所有可能出现的异常,然后采取以下解决措施。

Ø 考虑避免异常,彻底杜绝异常的发生;若不能完全避免,则尽可能地减小异常发生的几率。

Ø 如果有些异常不可避免,那么应该预先准备好处理异常的措施,从而降低或弥补异常造成的损失,或者恢复正常的流程。

Ø 对于某个系统遇到的异常,系统本身应尽可能地处理异常,实在没办法处理,才求助于其他系统来处理。因为有些异常需要系统本身及其他系统共同来处理,例如大楼里发生严重火灾,仅靠大楼里的灭火器是无法完全灭火的,还需要消防队的参与才能灭火;还有些异常系统本身不能处理,要完全依靠其他系统来处理。

异常剖析

异常(exception)是在运行时代码中产生的一种异常情况,是一个运行时错误,如数组越界和文件找不到等,这些事件的发生将阻止程序的正常运行。捕获错误最理想的是在编译期间,最好在运行程序以前,但并非所有错误都能在编译期间侦测到有些问题必须在运行期间解决。这时就需让错误的缔结者通过一些方法向接收者传递一些适当的信息,使其知道该如何正确地处理遇到的问题。解决的方法是在错误控制中排除所有偶然性,强制格式的正确

目的是使用尽可能精简的代码创建大型、可靠的应用程序,同时排除程序里那些不能控制的错误。

运行原理

Ø 一个方法的运行过程中,如果发生了例外,则该方法将生成一个相应类型的异常对象,并把其交给运行时系统,这过程被称为抛出。运行时系统在接收到异常后,会寻找相应的代码来处理,这一过程被称为捕获。如果运行时系统未找到异常的处理代码,将终止程序运行:若找到异常处理部分则执行处理代码,使程序继续执行下去。

Ø 当一个方法正常执行完毕,jvm 会从调用栈中弹出该方法的栈结构,然后继续处理前一个方法。如果在执行方法的过程中抛出异常,则jvm必须找到能捕获该异常的catch代码块。它首先查看当前方法是否存在这样的catch代码块,存在就执行该catch代码块;否则,jvm会从调用栈中弹出该方法的栈结构,继续到前一个方法中查找合适的catch代码块。在回溯过程中,如果jvm在某个方法中找到了处理该异常的代码块,则该方法的栈结构将成为栈顶元素,程序流程将转到该方法的异常处理代码部分继续执行。当jvm追溯到调用栈的底部的方法时,如果仍然没有找到处理该异常的代码块,将调用异常对象的printStackTrace()方法,打印来自方法调用栈的异常信息。如果该线程不是主线程,那么终止这个线程,其他线程继续正常运行。如果该线程是主线程(即方法调用栈的底部为main()方法),那么整个应用程序被终止。

java异常处理机制

Ø 要在程序中处理异常,主要考虑两个问题:(1)如何表示异常情况?(2)如何控制处理异常的流程

好处

Ø java通过面向对象的方法来处理异常事件。把各种不同类型的异常情况进行分类,把异常情况表示成异常类,可以充分发挥类的可扩展和可重用的优势。

Ø 在一些传统的编程语言,如C语言中,并没有专门处理异常的机制. 程序员通常用方法的特定返回值来表示异常情况,并且程序的正常流程和异常流程都采用同样的流程控制语句。它能加强程序的健壮性。如果不使用异常,就必须靠人为的去检查错误,并在程序中的许多地方去处理它;而使用异常,就不必在方法调用处进行检查,因为异常机制将保证能够捕获这个错误,并且只需在一个地方处理错误,即所谓的异常处理程序。为了加强程序的健壮性,在程序设计时,必须考虑到可能发生的异常事件并做出相应的处理

Ø 异常流程的代码和正常流程的代码分离,提高了程序的可读性,简化了程序的结构,便于调试。这种方式不仅节省代码,而且把“描述在正常执行过程中做什么事”的代码和“出了问题怎么办”的代码相分离,使代码结构清晰

Ø 可以灵活地处理异常,如果当前方法有能力处理异常,就捕获并处理它,否则只需抛出异常,由方法调用者来处理它。

异常使用原则

Ø 异常只能用于非正常情况,不能用异常来控制程序的正常流程

当异常发生时,jvm需要执行额外的操作,来定位处理异常的代码块,这时会降低性能。如果抛出异常的代码块和捕获异常的代码块位于同一个方法中,这种影响就会小一些;如果jvm必须搜索方法调用栈来寻找异常处理代码块,对性能的影响就较大了。因此,不应使用异常处理机制来控制程序的正常流程,而应该确保仅仅在程序中可能出现异常的地方使try```catch语句。此外,如果当前方法具备处理某种异常的能力,就尽量自行处理,不要把自己可以处理的异常推给方法调用者处理。

Ø 应尽可能地避免异常,尤其是运行时异常。许多运行时异常是由于程序代码中的错误引起的,只要修改了程序代码的错误,或者改进了程序的实现方式,就能避免这种错误。有些异常是由于当对象处于某种状态时,不合适某种操作而造成的。例如当高压锅内的水蒸气的压力很大时,突然打开锅盖会导致爆炸。为了避免这类事故,高压锅应提供状态测试功能,让使用者在打开锅盖前,判断高压锅内的水蒸气压力,是否合适进行打开锅盖的操作

Ø 当异常发生后,应尽量使各个对象的状态恢复到异常发生前的初始状态,而不至于停留在某个不合理的中间状态。

Ø 避免过于庞大的try代码块。try代码块越庞大,出现异常的地方就越多,要分析发生异常的原因就越困难。有效的做法是分割各个可能出现异常的程序段落,把它们分别放在单独的try代码块中,从而分别捕获异常。

Ø catch子句中指定具体的异常类型。为图省事,许多人用catch(Exception e)子句来捕获所有异常,这不是好的编程习惯,因为这意味着对各种异常采用同样的处理方式,这是不合理的,而且这样会捕获本应抛出的运行时异常,掩盖程序中的错误。

Ø 不要在catch代码块中忽略被捕获的异常。只要异常发生,就意味着某些地方出了问题,应该提供处理异常的措施。假如在catch代码块中不能采取任何措施,那就不要使用catch代码块捕获异常,而是用throws子句将异常抛出。

 

Throwable分类:

 

Error:表示仅靠程序本身无法恢复的严重错误。一般指虚拟机相关的问题,如系统崩溃、虚拟机出错、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断。Error类对象由Java虚拟机生成并抛出,遇到这样的错误,建议让程序终止

Exception表示程序中可能会出现的错误,是程序本身可以处理的异常。又分为以下二大类

1. 编译时异常:

Ø CheckedException,即Exception中除了RuntimeException体系的Exception类。

Ø 受检查异常表示只要通过处理,就可能使程序恢复运行。

Ø 如果抛出此异常对象没有处理,编译就不会通过。

2. 运行时异常:

Ø RuntimeException及其子类。运行时异常通常是由程序代码中的错误造成的,因此要尽量避免它。

Ø 这种异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常时,即使没有处理它,还是会编译通过。

Ø 产生该异常对象后不用处理它,因为该异常会立刻中止程序。而且假设处理成功使程序恢复运行,也可能会导致程序的业务逻辑错乱,甚至导致更严重的异常,或得到错误的运行结果。

Ø RuntimeException特别有助于调试某些特殊类型的编程错误,那些是编译器检测不到的。

3. 补充:Java认为Checked异常都是可以在编译阶段被处理的异常,所以它强制程序处理所有的Checked异常,而Runtime

异常则无须处理

ErrorRuntimeException的异同

相同:

java编译器都不会检查它们,当程序运行时出现它们,都会终止程序。

不同:

Error类及其子类表示的错误通常是由jvm抛出的,在JDK中预定义了一些错误类,一般不会扩展Error类来创建用户自定义的错误类。而RuntimeException类表示程序代码中的错误,它是可以扩展的,用户可以根据特定的问题领域来创建相关的运行时异常类。

Throwable类常用的方法:

    getMessage()---返回String类型的异常信息

    printStackTrace()—打印跟踪方法调用栈而获得的详细异常信息。在程序调试阶段,此方法可用于跟踪错误。

异常处理原则

Ø 问题出现了,你也许不清楚该如何处理,但你不应置之不理。你要停下来,看看是不是有别的地方能够处理这个问题。只是在当前环境中还没有足够的信息来解决这个问题,所以就把这个问题提交到一个更高级别的环境中去作出正确的决定。

异常的二种处理方法

开发时,一般会采取统一方式来处理异常

一种是使用try-catchtry{//可能会发生异常的代码} catch(希望捕获的异常类型){ 处理该异常的代码}

1. try{}catch(Exception 对象){} //一般处理原则:有几个具体的异常就有几个catch

2. try{} fianlly{}  //用法比如:服务器不管有无异常,都要关闭资源

3. try{} catch(Exception对象){} finally{} //产生的异常对象会逐步与catch语句中的异常类型进行匹配,匹配成功则执行相应处理代码,不成功则最终抛给虚拟机处理

4. 注意:不能单独使用try,必须与catchfinally配对出现。当使用多catch语句时,异常子类必须在它们父类之前。

5. try代码块后面有多个catch代码块时,jvm会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或其子类的实例,就执行这个catch代码块,而不会再执行其他的catch代码块。

6. throw语句后面不允许紧跟其他语句,因为这些语句永远不会被执行。

7. finally块用于关闭资源等,执行结果在方法return返回值之前。finally块总会被执行,除非在finally语句之前执行了退出虚拟机的方法 System.exit(1)exit()方法的参数status表示程序终止时的状态码,按照编程惯例,零表示正常终止,非零数字表示异常终止。如果在执行finally之前的代码块时,电脑突然断电,所有进程都终止运行,也不会执行finally语句。

8. finally代码块虽然在return语句之前被执行,但finally代码块不能通过重新给变量赋值的方式来改变return语句的返回值。

另一种是使用throws

u 若当前方法不知道应该如何处理这种异常,则该异常应抛给上一级调用者处理,如果main方法也不知道该如何处理,则使用throws声明抛出该异常,该异常最终将交由JVM处理。JVM对异常的处理方法是:打印异常跟踪栈信息,并中止程序运行,这就是程序在遇到异常后自动结束的原因。

u 如果某段代码中调用了一个带throws声明的方法,该方法声明抛出了Checked异常,这表明该方法希望它的调用者来处理该异常。也就是说,这段代码要么放在try块中显式捕获该异常,要么在这段代码所处方法上抛出该异常。

u throws 和 throw的区别:Throws是放在函数上的,用来抛异常类,可以抛多个;throw是放在函数中,用来抛异           常对象(后面跟着new),只能抛一个。

异常转换

Ø 客户层访问业务逻辑层,而业务逻辑层访问数据库层。数据库层把异常抛给业务逻辑层,业务逻辑层把异常抛给客户层,客户层则把异常抛给终端用户。当位于最上层的子系统不需要关心来自底层的异常的细节时,常见的做法是捕获原始的异常,把它转换为一个新的不同类型的异常再抛出,这种处理异常的办法称为异常转换 。

Ø 例如,假设终端用户通过客户界面把一个图像文件上传到数据库中,客户层调用业务逻辑层的uploadImageFile()方法去执行上传图像文件操作,此时可能会抛出IOException,但用户没必要关心IOException异常的细节,他仅需知道上传图像失败就可以了。因此,当uploadImageFile()方法抛出IOException异常后,应在catch代码块中先把该异常信息记入日志然后向用户抛出上传失败异常。具体的调试和排错由系统管理员或者软件开发人员来处理。

Ø 如果某个方法出现了无法处理的异常,则应抛给上级调用者处理。如果判断出上级调用者也处理不了,则应把异常转换成上级调用者能处理的异常。

自定义异常

java中没提供想要的异常时,那么就要根据需要自定义异常。

步骤:1. 创建一个类,继承异常类。

2 .自定义构造方法。在程序中可以自己定义一个判断,当条件不满足时就抛出自定义异常

继承时关于异常的处理

在继承父类或者接口的时候,只能抛和父类异常相等或其子类,不能抛比父类异常还要多的异常。但是如果真的有,那应该要自己处理掉,如果自己没有能力处理就要用RuntimeEcxeption或其子类,让程序中断。

日志&调试器

为什么需要日志

q 监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。

q 跟踪代码运行进轨迹,作为日后审计的依据。

q 担当集成开发环境中的调试器,向文件或控制台打印代码的调试信息。 

日志的使用: 最简单的方法就是建立一个java.util.logging.Logger实例 

7种日志级别 

Ø SEVEREWARNINGINFOCONFIGFINEFINERFINEST 

Ø 其中SEVERE即用于处理错误以及灾难事件。而FINEFINERFINEST级是用于处理一些不那么重要的信息,以及用于程序调试。 

Ø 缺省的消息记录级别为:INFO在缺省情况下我们在控制台看不见低于INFO级别的日志消息 

Ø 可以设定日志级别。logger.setLevel(Level.FINE) 

调试器

q 找到引发错误的代码并修正

q 断点,就是你想让程序运行到哪条语句停止 


DateCalendarDateFormat

java.util.Date

Ø 包装了一个long类型数据,表示与19701100:00:00这一刻所相距的毫秒数。Date类用于表示日期和时间

Ø 由于开始设计Date时没有考虑到国际化,所以后来又设计了DateFormat类和Calendar类来解决Date类中的问题

Ø Date类的默认构造方法调用System_currentTimeMillis{)方法获取当前时间,

new Date()语句等价于:new Date(System.currentTimeMillis())

Ø Date.getTime():日期对象转成毫秒值。

setTime():毫秒值转成日期对象。

java. text.DateFormat抽象类

Ø 用于定制日期的格式,它有一个具体子类为java.text.SimpleDateFormat

1, format(Date date):Date格式转化为日期或者时间的字符串

2, DateFormat getDateInstance():获取日期,按照默认的格式。

3, Date parse(String source,ParsePosition pos):根据给定的规则生成日期和时间字符串

4, // 设置日期格式, new Date()为获取当前系统时间

String strTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

.format(new Date());

java.util.Calendar

1, Calendar getInstance():使用静态方法,返回这个类对象

2, Add(int field,int amount):增加或减去指定的时间。

3, Int get(int field):返回给定的字段的值。

4, Set(int year, int month, int date):设置时间

SystemRuntime

Ø Java不支持全局方法和变量,Java设计者将一些系统相关的重要方法和变量收集到了一个统一的类中,这就是System类 

Ø Lang型中System类里面都是静态方法,要使用直接用类名.方法就可以调用了。

  1currentTimeMillis():返回以毫秒为单位的当前时间。

  2exit():终止java虚拟机

  3getProperties():返回Properties确定当前系统属性。

  4setProperty(String key, String value):自定义键值的系统属性。

Ø Runtime类封装了Java命令本身的运行进程,其中的许多方法与System中的方法重复,是单例设计模式

String shell;

if (file.isDirectory()) {

shell = "ls " + file.getCanonicalPath() + " -lad";// 获得当前目录的权限

else {

shell = "ls " + file.getCanonicalPath() + " -l";// 获得当前文件的权限

}

Runtime runtime = Runtime.getRuntime();// 获取runtime对象来执行shell脚本

Process process = runtime.exec(shell); // 执行脚本

InputStream inputStream = process.getInputStream();// 获取脚本执行的结果流

异常

引子:异常情况会改变正常的流程,导致恶劣的后果。为了减少损失,应事先充分预计所有可能出现的异常,然后采取以下解决措施。

Ø 考虑避免异常,彻底杜绝异常的发生;若不能完全避免,则尽可能地减小异常发生的几率。

Ø 如果有些异常不可避免,那么应该预先准备好处理异常的措施,从而降低或弥补异常造成的损失,或者恢复正常的流程。

Ø 对于某个系统遇到的异常,系统本身应尽可能地处理异常,实在没办法处理,才求助于其他系统来处理。因为有些异常需要系统本身及其他系统共同来处理,例如大楼里发生严重火灾,仅靠大楼里的灭火器是无法完全灭火的,还需要消防队的参与才能灭火;还有些异常系统本身不能处理,要完全依靠其他系统来处理。

异常剖析

异常(exception)是在运行时代码中产生的一种异常情况,是一个运行时错误,如数组越界和文件找不到等,这些事件的发生将阻止程序的正常运行。捕获错误最理想的是在编译期间,最好在运行程序以前,但并非所有错误都能在编译期间侦测到有些问题必须在运行期间解决。这时就需让错误的缔结者通过一些方法向接收者传递一些适当的信息,使其知道该如何正确地处理遇到的问题。解决的方法是在错误控制中排除所有偶然性,强制格式的正确

目的是使用尽可能精简的代码创建大型、可靠的应用程序,同时排除程序里那些不能控制的错误。

运行原理

Ø 一个方法的运行过程中,如果发生了例外,则该方法将生成一个相应类型的异常对象,并把其交给运行时系统,这过程被称为抛出。运行时系统在接收到异常后,会寻找相应的代码来处理,这一过程被称为捕获。如果运行时系统未找到异常的处理代码,将终止程序运行:若找到异常处理部分则执行处理代码,使程序继续执行下去。

Ø 当一个方法正常执行完毕,jvm 会从调用栈中弹出该方法的栈结构,然后继续处理前一个方法。如果在执行方法的过程中抛出异常,则jvm必须找到能捕获该异常的catch代码块。它首先查看当前方法是否存在这样的catch代码块,存在就执行该catch代码块;否则,jvm会从调用栈中弹出该方法的栈结构,继续到前一个方法中查找合适的catch代码块。在回溯过程中,如果jvm在某个方法中找到了处理该异常的代码块,则该方法的栈结构将成为栈顶元素,程序流程将转到该方法的异常处理代码部分继续执行。当jvm追溯到调用栈的底部的方法时,如果仍然没有找到处理该异常的代码块,将调用异常对象的printStackTrace()方法,打印来自方法调用栈的异常信息。如果该线程不是主线程,那么终止这个线程,其他线程继续正常运行。如果该线程是主线程(即方法调用栈的底部为main()方法),那么整个应用程序被终止。

java异常处理机制

Ø 要在程序中处理异常,主要考虑两个问题:(1)如何表示异常情况?(2)如何控制处理异常的流程

好处

Ø java通过面向对象的方法来处理异常事件。把各种不同类型的异常情况进行分类,把异常情况表示成异常类,可以充分发挥类的可扩展和可重用的优势。

Ø 在一些传统的编程语言,如C语言中,并没有专门处理异常的机制. 程序员通常用方法的特定返回值来表示异常情况,并且程序的正常流程和异常流程都采用同样的流程控制语句。它能加强程序的健壮性。如果不使用异常,就必须靠人为的去检查错误,并在程序中的许多地方去处理它;而使用异常,就不必在方法调用处进行检查,因为异常机制将保证能够捕获这个错误,并且只需在一个地方处理错误,即所谓的异常处理程序。为了加强程序的健壮性,在程序设计时,必须考虑到可能发生的异常事件并做出相应的处理

Ø 异常流程的代码和正常流程的代码分离,提高了程序的可读性,简化了程序的结构,便于调试。这种方式不仅节省代码,而且把“描述在正常执行过程中做什么事”的代码和“出了问题怎么办”的代码相分离,使代码结构清晰

Ø 可以灵活地处理异常,如果当前方法有能力处理异常,就捕获并处理它,否则只需抛出异常,由方法调用者来处理它。

异常使用原则

Ø 异常只能用于非正常情况,不能用异常来控制程序的正常流程

当异常发生时,jvm需要执行额外的操作,来定位处理异常的代码块,这时会降低性能。如果抛出异常的代码块和捕获异常的代码块位于同一个方法中,这种影响就会小一些;如果jvm必须搜索方法调用栈来寻找异常处理代码块,对性能的影响就较大了。因此,不应使用异常处理机制来控制程序的正常流程,而应该确保仅仅在程序中可能出现异常的地方使try```catch语句。此外,如果当前方法具备处理某种异常的能力,就尽量自行处理,不要把自己可以处理的异常推给方法调用者处理。

Ø 应尽可能地避免异常,尤其是运行时异常。许多运行时异常是由于程序代码中的错误引起的,只要修改了程序代码的错误,或者改进了程序的实现方式,就能避免这种错误。有些异常是由于当对象处于某种状态时,不合适某种操作而造成的。例如当高压锅内的水蒸气的压力很大时,突然打开锅盖会导致爆炸。为了避免这类事故,高压锅应提供状态测试功能,让使用者在打开锅盖前,判断高压锅内的水蒸气压力,是否合适进行打开锅盖的操作

Ø 当异常发生后,应尽量使各个对象的状态恢复到异常发生前的初始状态,而不至于停留在某个不合理的中间状态。

Ø 避免过于庞大的try代码块。try代码块越庞大,出现异常的地方就越多,要分析发生异常的原因就越困难。有效的做法是分割各个可能出现异常的程序段落,把它们分别放在单独的try代码块中,从而分别捕获异常。

Ø catch子句中指定具体的异常类型。为图省事,许多人用catch(Exception e)子句来捕获所有异常,这不是好的编程习惯,因为这意味着对各种异常采用同样的处理方式,这是不合理的,而且这样会捕获本应抛出的运行时异常,掩盖程序中的错误。

Ø 不要在catch代码块中忽略被捕获的异常。只要异常发生,就意味着某些地方出了问题,应该提供处理异常的措施。假如在catch代码块中不能采取任何措施,那就不要使用catch代码块捕获异常,而是用throws子句将异常抛出。

 

Throwable分类:

 

Error:表示仅靠程序本身无法恢复的严重错误。一般指虚拟机相关的问题,如系统崩溃、虚拟机出错、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断。Error类对象由Java虚拟机生成并抛出,遇到这样的错误,建议让程序终止

Exception表示程序中可能会出现的错误,是程序本身可以处理的异常。又分为以下二大类

1. 编译时异常:

Ø CheckedException,即Exception中除了RuntimeException体系的Exception类。

Ø 受检查异常表示只要通过处理,就可能使程序恢复运行。

Ø 如果抛出此异常对象没有处理,编译就不会通过。

2. 运行时异常:

Ø RuntimeException及其子类。运行时异常通常是由程序代码中的错误造成的,因此要尽量避免它。

Ø 这种异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常时,即使没有处理它,还是会编译通过。

Ø 产生该异常对象后不用处理它,因为该异常会立刻中止程序。而且假设处理成功使程序恢复运行,也可能会导致程序的业务逻辑错乱,甚至导致更严重的异常,或得到错误的运行结果。

Ø RuntimeException特别有助于调试某些特殊类型的编程错误,那些是编译器检测不到的。

3. 补充:Java认为Checked异常都是可以在编译阶段被处理的异常,所以它强制程序处理所有的Checked异常,而Runtime

异常则无须处理

ErrorRuntimeException的异同

相同:

java编译器都不会检查它们,当程序运行时出现它们,都会终止程序。

不同:

Error类及其子类表示的错误通常是由jvm抛出的,在JDK中预定义了一些错误类,一般不会扩展Error类来创建用户自定义的错误类。而RuntimeException类表示程序代码中的错误,它是可以扩展的,用户可以根据特定的问题领域来创建相关的运行时异常类。

Throwable类常用的方法:

    getMessage()---返回String类型的异常信息

    printStackTrace()—打印跟踪方法调用栈而获得的详细异常信息。在程序调试阶段,此方法可用于跟踪错误。

异常处理原则

Ø 问题出现了,你也许不清楚该如何处理,但你不应置之不理。你要停下来,看看是不是有别的地方能够处理这个问题。只是在当前环境中还没有足够的信息来解决这个问题,所以就把这个问题提交到一个更高级别的环境中去作出正确的决定。

异常的二种处理方法

开发时,一般会采取统一方式来处理异常

一种是使用try-catchtry{//可能会发生异常的代码} catch(希望捕获的异常类型){ 处理该异常的代码}

1. try{}catch(Exception 对象){} //一般处理原则:有几个具体的异常就有几个catch

2. try{} fianlly{}  //用法比如:服务器不管有无异常,都要关闭资源

3. try{} catch(Exception对象){} finally{} //产生的异常对象会逐步与catch语句中的异常类型进行匹配,匹配成功则执行相应处理代码,不成功则最终抛给虚拟机处理

4. 注意:不能单独使用try,必须与catchfinally配对出现。当使用多catch语句时,异常子类必须在它们父类之前。

5. try代码块后面有多个catch代码块时,jvm会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或其子类的实例,就执行这个catch代码块,而不会再执行其他的catch代码块。

6. throw语句后面不允许紧跟其他语句,因为这些语句永远不会被执行。

7. finally块用于关闭资源等,执行结果在方法return返回值之前。finally块总会被执行,除非在finally语句之前执行了退出虚拟机的方法 System.exit(1)exit()方法的参数status表示程序终止时的状态码,按照编程惯例,零表示正常终止,非零数字表示异常终止。如果在执行finally之前的代码块时,电脑突然断电,所有进程都终止运行,也不会执行finally语句。

8. finally代码块虽然在return语句之前被执行,但finally代码块不能通过重新给变量赋值的方式来改变return语句的返回值。

另一种是使用throws

u 若当前方法不知道应该如何处理这种异常,则该异常应抛给上一级调用者处理,如果main方法也不知道该如何处理,则使用throws声明抛出该异常,该异常最终将交由JVM处理。JVM对异常的处理方法是:打印异常跟踪栈信息,并中止程序运行,这就是程序在遇到异常后自动结束的原因。

u 如果某段代码中调用了一个带throws声明的方法,该方法声明抛出了Checked异常,这表明该方法希望它的调用者来处理该异常。也就是说,这段代码要么放在try块中显式捕获该异常,要么在这段代码所处方法上抛出该异常。

u throws 和 throw的区别:Throws是放在函数上的,用来抛异常类,可以抛多个;throw是放在函数中,用来抛异           常对象(后面跟着new),只能抛一个。

异常转换

Ø 客户层访问业务逻辑层,而业务逻辑层访问数据库层。数据库层把异常抛给业务逻辑层,业务逻辑层把异常抛给客户层,客户层则把异常抛给终端用户。当位于最上层的子系统不需要关心来自底层的异常的细节时,常见的做法是捕获原始的异常,把它转换为一个新的不同类型的异常再抛出,这种处理异常的办法称为异常转换 。

Ø 例如,假设终端用户通过客户界面把一个图像文件上传到数据库中,客户层调用业务逻辑层的uploadImageFile()方法去执行上传图像文件操作,此时可能会抛出IOException,但用户没必要关心IOException异常的细节,他仅需知道上传图像失败就可以了。因此,当uploadImageFile()方法抛出IOException异常后,应在catch代码块中先把该异常信息记入日志然后向用户抛出上传失败异常。具体的调试和排错由系统管理员或者软件开发人员来处理。

Ø 如果某个方法出现了无法处理的异常,则应抛给上级调用者处理。如果判断出上级调用者也处理不了,则应把异常转换成上级调用者能处理的异常。

自定义异常

java中没提供想要的异常时,那么就要根据需要自定义异常。

步骤:1. 创建一个类,继承异常类。

2 .自定义构造方法。在程序中可以自己定义一个判断,当条件不满足时就抛出自定义异常

继承时关于异常的处理

在继承父类或者接口的时候,只能抛和父类异常相等或其子类,不能抛比父类异常还要多的异常。但是如果真的有,那应该要自己处理掉,如果自己没有能力处理就要用RuntimeEcxeption或其子类,让程序中断。

日志&调试器

为什么需要日志

q 监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。

q 跟踪代码运行进轨迹,作为日后审计的依据。

q 担当集成开发环境中的调试器,向文件或控制台打印代码的调试信息。 

日志的使用: 最简单的方法就是建立一个java.util.logging.Logger实例 

7种日志级别 

Ø SEVEREWARNINGINFOCONFIGFINEFINERFINEST 

Ø 其中SEVERE即用于处理错误以及灾难事件。而FINEFINERFINEST级是用于处理一些不那么重要的信息,以及用于程序调试。 

Ø 缺省的消息记录级别为:INFO在缺省情况下我们在控制台看不见低于INFO级别的日志消息 

Ø 可以设定日志级别。logger.setLevel(Level.FINE) 

调试器

q 找到引发错误的代码并修正

q 断点,就是你想让程序运行到哪条语句停止 






你可能感兴趣的:(java)