87.java基础4面向对象下

51.单例的另一种方式:

final:最终的
1.可以用来修饰:类、方法、变量
2.具体的:
2.1 final 用来修饰一个类:此类不能被其他类所继承。
 *          比如:String类、System类、StringBuffer类
2.2 final 用来修饰方法:表明此方法不可以被重写
 * 			比如:Object类中getClass();
2.3 final 用来修饰变量:此时的"变量"就称为是一个常量
 * 	    1. final修饰属性:可以考虑赋值的位置:显式初始化、代码块中初始化、构造器中初始化
 * 	    2. final修饰局部变量:
 *        尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。
static final 用来修饰属性:全局常量

52.abstract关键字

package com.atguigu.java;
/*
 * abstract关键字的使用
 * 1.abstract:抽象的
 * 2.abstract可以用来修饰的结构:类、方法
 * 3. abstract修饰类:抽象类
 * 		> 此类不能实例化
 *      > 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
 *      > 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
 * 4. abstract修饰方法:抽象方法
 * 		> 抽象方法只有方法的声明,没有方法体
 * 		> 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
 *      > 若子类重写了父类中的所有的抽象方法后,此子类方可实例化
 *        若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
 
 * abstract使用上的注意点:
 * 1.abstract不能用来修饰:属性、构造器等结构 
 * 2.abstract不能用来修饰私有方法、静态方法、final的方法、final的类
 */
public class AbstractTest {
	public static void main(String[] args) {
		
		//一旦Person类抽象了,就不可实例化
//		Person p1 = new Person();
//		p1.eat();		
	}
}
abstract class Creature{
	public abstract void breath();
}
abstract class Person extends Creature{
	String name;
	int age;	
	public Person(){		
	}
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}	
	//不是抽象方法:
//	public void eat(){
//		
//	}
	//抽象方法
	public abstract void eat();	
	public void walk(){
		System.out.println("人走路");
	}		
}
class Student extends Person{	
	public Student(String name,int age){
		super(name,age);
	}
	public Student(){
	}	
	public void eat(){
		System.out.println("学生多吃有营养的食物");
	}
	@Override
	public void breath() {
		System.out.println("学生应该呼吸新鲜的没有雾霾的空气");
	}
}

问题:
	1.问什么抽象类不可以使用final关键字声明?
     因为抽象类希望被子类继承,final修饰的类不可以被继承
     2.一个抽象类中可以定义构造器么?
     可以
     

53.抽象类的匿名子类

package com.atguigu.java;
/*
 * 抽象类的匿名子类
 */
public class PersonTest {	
	public static void main(String[] args) {		
		method(new Student());//匿名对象(对象没有名称直接实例化)		
		Worker worker = new Worker();
		method1(worker);//非匿名的类非匿名的对象(可以知道对象是由哪个类实例化的,也进行赋值worker)	 
		method1(new Worker());//非匿名的类匿名的对象		
		System.out.println("********************");		
		//创建了一匿名子类的对象:p
		Person p = new Person(){   //由于Person是抽象类,不能实例化,但是通过显式的重写的抽象方法,所以叫做(匿名子类对象)
			@Override
			public void eat() {
				System.out.println("吃东西");
			}
			@Override
			public void breath() {
				System.out.println("好好呼吸");
			}			
		};
		
		method1(p);
		System.out.println("********************");
		//创建匿名子类的匿名对象
		method1(new Person(){
			@Override
			public void eat() {
				System.out.println("吃好吃东西");
			}
			@Override
			public void breath() {
				System.out.println("好好呼吸新鲜空气");
			}
		});
	}	
	public static void method1(Person p){
		p.eat();
		p.breath();
	}	
	public static void method(Student s){		
	}
}
class Worker extends Person{  ///其中Person是一个抽象类
	@Override
	public void eat() {
	}
	@Override
	public void breath() {
	}	
}
---------------------------------------------抽象类模板类设计模式1--------------------------------------
package com.atguigu.java;
/*
 * 抽象类的应用:模板方法的设计模式
 * 
 */
public class TemplateTest {
	public static void main(String[] args) {		
		SubTemplate t = new SubTemplate();		
		t.spendTime();
	}
}
abstract class Template{	
	//计算某段代码执行所需要花费的时间
	public void spendTime(){		
		long start = System.currentTimeMillis();		
		this.code();//不确定的部分、易变的部分		
		long end = System.currentTimeMillis();		
		System.out.println("花费的时间为:" + (end - start));		
	}	
	public abstract void code();		
}
class SubTemplate extends Template{
	@Override
	public void code() {		
		for(int i = 2;i <= 1000;i++){
			boolean isFlag = true;
			for(int j = 2;j <= Math.sqrt(i);j++){
				
				if(i % j == 0){
					isFlag = false;
					break;
				}
			}
			if(isFlag){
				System.out.println(i);
			}
		}
	}	
}
------------------------------------------抽象类模板类设计模式2-----------------------------------------
package com.atguigu.java;
//抽象类的应用:模板方法的设计模式
public class TemplateMethodTest {

	public static void main(String[] args) {
		BankTemplateMethod btm = new DrawMoney();
		btm.process();
		BankTemplateMethod btm2 = new ManageMoney();
		btm2.process();
	}
}
abstract class BankTemplateMethod {
	// 具体方法
	public void takeNumber() {
		System.out.println("取号排队");
	}
	public abstract void transact(); // 办理具体的业务 //钩子方法
	public void evaluate() {
		System.out.println("反馈评分");
	}
	// 模板方法,把基本操作组合到一起,子类一般不能重写
	public final void process() {
		this.takeNumber();
		this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码
		this.evaluate();
	}
}
class DrawMoney extends BankTemplateMethod {
	public void transact() {
		System.out.println("我要取款!!!");
	}
}
class ManageMoney extends BankTemplateMethod {
	public void transact() {
		System.out.println("我要理财!我这里有2000万美元!!");
	}
}

54.final说明:

http://10.20.85.121:8080/test_path/1k.html

55.java接口:

package com.atguigu.java1;
/*
 * 接口的使用
 * 1.接口使用interface来定义
 * 2.Java中,接口和类是并列的两个结构
 * 3.如何定义接口:定义接口中的成员 		
 * 		3.1 JDK7及以前:只能定义全局常量和抽象方法
 * 			>全局常量:public static final的.但是书写时,可以省略不写
 * 			>抽象方法:public abstract的		
 * 		3.2 JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法(略)
 * 4. 接口中不能定义构造器的!意味着接口不可以实例化
 * 5. Java开发中,接口通过让类去实现(implements)的方式来使用.
 *    如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
 *    如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
 * 6. Java类可以实现多个接口   --->弥补了Java单继承性的局限性
 *   格式:class AA extends BB implements CC,DD,EE
 * 7. 接口与接口之间可以继承,而且可以多继承
 * *******************************
 * 8. 接口的具体使用,体现多态性
 * 9. 接口,实际上可以看做是一种规范
 * 面试题:抽象类与接口有哪些异同?
 */
public class InterfaceTest {
	public static void main(String[] args) {
		System.out.println(Flyable.MAX_SPEED);
		System.out.println(Flyable.MIN_SPEED);
//		Flyable.MIN_SPEED = 2;	
		Plane plane = new Plane();
		plane.fly();
	}}
interface Flyable{
	//全局常量
	public static final int MAX_SPEED = 7900;//第一宇宙速度
	int MIN_SPEED = 1;//省略了public static final
	//抽象方法
	public abstract void fly();
	//省略了public abstract
	void stop();	
	//Interfaces cannot have constructors
//	public Flyable(){
//		
//	}
}
interface Attackable{
	void attack();	
}
class Plane implements Flyable{
	@Override
	public void fly() {
		System.out.println("通过引擎起飞");
	}
	@Override
	public void stop() {
		System.out.println("驾驶员减速停止");
	}	
}
abstract class Kite implements Flyable{
	@Override
	public void fly() {	
	}	
}
class Bullet extends Object implements Flyable,Attackable,CC{
	@Override
	public void attack() {
		// TODO Auto-generated method stub	
	}
	@Override
	public void fly() {
		// TODO Auto-generated method stub		
	}
	@Override
	public void stop() {
		// TODO Auto-generated method stub	
	}
	@Override
	public void method1() {
		// TODO Auto-generated method stub	
	}
	@Override
	public void method2() {
		// TODO Auto-generated method stub		
	}	
}
//************************************
interface AA{
	void method1();
}
interface BB{	
	void method2();
}
interface CC extends AA,BB{
}

56.接口多态实现:

package com.atguigu.java1;
/*
 * 接口的使用
 * 1.接口使用上也满足多态性
 * 2.接口,实际上就是定义了一种规范
 * 3.开发中,体会面向接口编程!
 */
public class USBTest {
	public static void main(String[] args) {	
		Computer com = new Computer();
		//1.创建了接口的非匿名实现类的非匿名对象
		Flash flash = new Flash();
		com.transferData(flash);		
		//2. 创建了接口的非匿名实现类的匿名对象
		com.transferData(new Printer());		
		//3. 创建了接口的匿名实现类的非匿名对象
		USB phone = new USB(){
			@Override
			public void start() {
				System.out.println("手机开始工作");
			}
			@Override
			public void stop() {
				System.out.println("手机结束工作");
			}			
		};
		com.transferData(phone);		
		//4. 创建了接口的匿名实现类的匿名对象		
		com.transferData(new USB(){
			@Override
			public void start() {
				System.out.println("mp3开始工作");
			}
			@Override
			public void stop() {
				System.out.println("mp3结束工作");
			}
		});
	}
}
class Computer{	
	public void transferData(USB usb){//USB usb = new Flash();
		usb.start();		
		System.out.println("具体传输数据的细节");		
		usb.stop();
	}	
}
interface USB{
	//常量:定义了长、宽、最大最小的传输速度等	
	void start();	
	void stop();	
}
class Flash implements USB{
	@Override
	public void start() {
		System.out.println("U盘开启工作");
	}
	@Override
	public void stop() {
		System.out.println("U盘结束工作");
	}	
}

class Printer implements USB{
	@Override
	public void start() {
		System.out.println("打印机开启工作");
	}
	@Override
	public void stop() {
		System.out.println("打印机结束工作");
	}	
}

57.java接口实现代理类:

package com.atguigu.java1;
/*
 * 接口的应用:代理模式
 */
public class NetWorkTest {
	public static void main(String[] args) {
		Server server = new Server();
//		server.browse();
		ProxyServer proxyServer = new ProxyServer(server);		
		proxyServer.browse();		
	}
}
interface NetWork{	
	public void browse();	
}
//被代理类
class Server implements NetWork{
	@Override
	public void browse() {
		System.out.println("真实的服务器访问网络");
	}
}
//代理类
class ProxyServer implements NetWork{
	
	private NetWork work;
	
	public ProxyServer(NetWork work){
		this.work = work;
	}	
	public void check(){
		System.out.println("联网之前的检查工作");
	}	
	@Override
	public void browse() {
		check();
		
		work.browse();		
	}	
}

58.java接口练习题:

package com.atguigu.exer3;
/*
 * interface CompareObject{
	public int compareTo(Object o);   
	//若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
 }

 */
public interface CompareObject {
	//若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
	public int compareTo(Object o); 
}
--------------------------------------------------------------------------------
package com.atguigu.exer3;
/*
 * 定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。
 * 在ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半径大小。
 */
public class ComparableCircle extends Circle implements CompareObject{
	
	public ComparableCircle(double radius) {
		super(radius);
	}
	@Override
	public int compareTo(Object o) {
		if(this == o){
			return 0;
		}
		if(o instanceof ComparableCircle){
			ComparableCircle c = (ComparableCircle)o;
			//错误的:
//			return (int) (this.getRadius() - c.getRadius());
			//正确的方式一:
//			if(this.getRadius() > c.getRadius()){
//				return 1;
//			}else if(this.getRadius() < c.getRadius()){
//				return -1;
//			}else{
//				return 0;
//			}
			//当属性radius声明为Double类型时,可以调用包装类的方法
			//正确的方式二:
			return this.getRadius().compareTo(c.getRadius());
		}else{
//			return 0;
			throw new RuntimeException("传入的数据类型不匹配");
		}	
	}	
}
------------------------------------------------------------------------------------------
package com.atguigu.exer3;
/*
 * 定义一个Circle类,声明radius属性,提供getter和setter方法
 */
public class Circle {	
	private Double radius;
	public Double getRadius() {
		return radius;
	}
	public void setRadius(Double radius) {
		this.radius = radius;
	}
	public Circle() {
		super();
	}
	public Circle(Double radius) {
		super();
		this.radius = radius;
	}
}
------------------------------------------------------------------------------------------
package com.atguigu.exer3;
public class ComparableCircleTest {
	public static void main(String[] args) {
		ComparableCircle c1 = new ComparableCircle(3.4);
		ComparableCircle c2 = new ComparableCircle(3.6);
		
		int compareValue = c1.compareTo(c2);
		if(compareValue > 0){
			System.out.println("c1对象大");
		}else if(compareValue < 0){
			System.out.println("c2对象大");
		}else{
			System.out.println("c1与c2一样大");
		}
		int compareValue1 = c1.compareTo(new String("AA"));
		System.out.println(compareValue1);
	}
}

59.java8接口扩展:

package com.atguigu.java8;

/*
 * JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
 */
public interface CompareA {
	//静态方法
	public static void method1(){
		System.out.println("CompareA:北京");
	}
	//默认方法
	public default void method2(){
		System.out.println("CompareA:上海");
	}
	default void method3(){
		System.out.println("CompareA:上海");
	}
}
------------------------------------------------------------------------------------------
package com.atguigu.java8;
public interface CompareB {
	default void method3(){
		System.out.println("CompareB:上海");
	}
}
------------------------------------------------------------------------------------------
package com.atguigu.java8;

public class SubClassTest {
	public static void main(String[] args) {
		SubClass s = new SubClass();	
//		s.method1();
//		SubClass.method1();
		//知识点1:接口中定义的静态方法,只能通过接口来调用。
		CompareA.method1();
		//知识点2:通过实现类的对象,可以调用接口中的默认方法。
		//如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
		s.method2();
		//知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,
		//那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。-->类优先原则
		//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,
		//那么在实现类没有重写此方法的情况下,报错。-->接口冲突。
		//这就需要我们必须在实现类中重写此方法
		s.method3();	
	}
}
class SubClass extends SuperClass implements CompareA,CompareB{
	public void method2(){
		System.out.println("SubClass:上海");
	}
	public void method3(){
		System.out.println("SubClass:深圳");
	}
	//知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
	public void myMethod(){
		method3();//调用自己定义的重写的方法
		super.method3();//调用的是父类中声明的
		//调用接口中的默认方法
		CompareA.super.method3();
		CompareB.super.method3();
	}
}
---------------------------------------------------------------------------------------
package com.atguigu.java8;
public class SuperClass {	
	public void method3(){
		System.out.println("SuperClass:北京");
	}	
}

60.java内部类:

package com.atguigu.java2;
/*
 * 类的内部成员之五:内部类
 * 1. Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
 * 2.内部类的分类:成员内部类(静态、非静态)  vs 局部内部类(方法内、代码块内、构造器内)
 * 3.成员内部类:
 * 		一方面,作为外部类的成员:
 * 			>调用外部类的结构
 * 			>可以被static修饰
 * 			>可以被4种不同的权限修饰
 * 		另一方面,作为一个类:
 * 			> 类内可以定义属性、方法、构造器等
 * 			> 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
 * 			> 可以被abstract修饰
 * 4.关注如下的3个问题
 *   4.1 如何实例化成员内部类的对象
 *   4.2 如何在成员内部类中区分调用外部类的结构
 *   4.3 开发中局部内部类的使用  见《InnerClassTest1.java》
 * 
 */
public class InnerClassTest {
	public static void main(String[] args) {
		//创建Dog实例(静态的成员内部类):
		Person.Dog dog = new Person.Dog();
		dog.show();
		//创建Bird实例(非静态的成员内部类):
//		Person.Bird bird = new Person.Bird();//错误的
		Person p = new Person();
		Person.Bird bird = p.new Bird();
		bird.sing();
		System.out.println();
		bird.display("黄鹂");
	}
}
class Person{
	String name = "小明";
	int age;
	public void eat(){
		System.out.println("人:吃饭");
	}
	//静态成员内部类
	static class Dog{
		String name;
		int age;
 
		public void show(){
			System.out.println("卡拉是条狗");
//			eat();
		}
	}
	//非静态成员内部类
	class Bird{
		String name = "杜鹃";
		public Bird(){
		}
		public void sing(){
			System.out.println("我是一只小小鸟");
			Person.this.eat();//调用外部类的非静态属性
			eat();
			System.out.println(age);
		}
 
		public void display(String name){
			System.out.println(name);//方法的形参
			System.out.println(this.name);//内部类的属性
			System.out.println(Person.this.name);//外部类的属性
		}
	}
	public void method(){
		//局部内部类
		class AA{
		}
	}
	{
		//局部内部类
		class BB{
		}
	}
	public Person(){
		//局部内部类
		class CC{
		}
	}
}
------------------------------------------------------------------------------------------
package com.atguigu.java2;
public class InnerClassTest1 {
	//开发中很少见
	public void method(){
		//局部内部类
		class AA{
		}
	}
	//返回一个实现了Comparable接口的类的对象
	public Comparable getComparable(){
		//创建一个实现了Comparable接口的类:局部内部类
		//方式一:
//		class MyComparable implements Comparable{
//
//			@Override
//			public int compareTo(Object o) {
//				return 0;
//			}		
//		}
//		return new MyComparable();
		//方式二:
		return new Comparable(){
			@Override
			public int compareTo(Object o) {
				return 0;
			}
		};
	}
}
-----------------------------------------内部类使用局部变量--------------------------------------
package com.atguigu.java;
public class InnerClassTest {
//	public void onCreate(){
//		int number = 10;
//		View.OnClickListern listener = new View.OnClickListener(){	
//			public void onClick(){
//				System.out.println("hello!");
//				System.out.println(number);
//			}}	
//		button.setOnClickListener(listener);	
//	}
	/*
	 * 在局部内部类的方法中(比如:show)如果调用局部内部类所声明的方法(比如:method)中的局部变量(比如:num)的话,
	 * 要求此局部变量声明为final的。
	 * jdk 7及之前版本:要求此局部变量显式的声明为final的
	 * jdk 8及之后的版本:可以省略final的声明
	 * 
	 */
	public void method(){
		//局部变量,是一个final的变量
		int num = 10;
		class AA{
			public void show(){
//				num = 20;
				System.out.println(num);
			}}}}

61.java异常

package com.atguigu.java;
/*
 * Error:
 * Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:*Error和OOM。
 * 一般不编写针对性的代码进行处理。
 */
public class ErrorTest {
	public static void main(String[] args) {
		//1.栈溢出:java.lang.*Error
//		main(args);
		//2.堆溢出:java.lang.OutOfMemoryError 
		Integer[] arr = new Integer[1024*1024*1024];
	}
}
------------------------------------------异常种类-------------------------------------------------
package com.atguigu.java1;
import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import java.util.Scanner;
import org.junit.Test;
/*
 * 一、异常体系结构
 * 
 * java.lang.Throwable
 * 		|-----java.lang.Error:一般不编写针对性的代码进行处理。
 * 		|-----java.lang.Exception:可以进行异常的处理
 * 			|------编译时异常(checked)
 * 					|-----IOException
 * 						|-----FileNotFoundException
 * 					|-----ClassNotFoundException
 * 			|------运行时异常(unchecked,RuntimeException)
 * 					|-----NullPointerException
 * 					|-----ArrayIndexOutOfBoundsException
 * 					|-----ClassCastException
 * 					|-----NumberFormatException
 * 					|-----InputMismatchException
 * 					|-----ArithmeticException
 * 
 * 
 * 
 * 面试题:常见的异常都有哪些?举例说明
 */
public class ExceptionTest {
	//******************以下是编译时异常***************************
	@Test
	public void test7(){
//		File file = new File("hello.txt");
//		FileInputStream fis = new FileInputStream(file);
//		
//		int data = fis.read();
//		while(data != -1){
//			System.out.print((char)data);
//			data = fis.read();
//		}
//		
//		fis.close();
	}
	//******************以下是运行时异常***************************
	//ArithmeticException
	@Test
	public void test6(){
		int a = 10;
		int b = 0;
		System.out.println(a / b);
	}
	//InputMismatchException
	@Test
	public void test5(){
		//输入不匹配
		Scanner scanner = new Scanner(System.in);
		int score = scanner.nextInt();
		System.out.println(score);
		scanner.close();
	}
	//NumberFormatException
	@Test
	public void test4(){
		//格式异常
		String str = "123";
		str = "abc";
		int num = Integer.parseInt(str);
	}
	//ClassCastException
	@Test
	public void test3(){
		//类型转换异常
		Object obj = new Date();
		String str = (String)obj;
	}
	//IndexOutOfBoundsException
	@Test
	public void test2(){
		//ArrayIndexOutOfBoundsException
//		int[] arr = new int[10];
//		System.out.println(arr[10]);
		//StringIndexOutOfBoundsException
		String str = "abc";
		System.out.println(str.charAt(3));
	}
	//NullPointerException
	@Test
	public void test1(){
//		int[] arr = null;
//		System.out.println(arr[3]);
		String str = "abc";
		str = null;
		System.out.println(str.charAt(0));
	}
}
--------------------------------------------try-catch-finally----------------------------------------
package com.atguigu.java1;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.junit.Test;
/*
 * 一、异常的处理:抓抛模型
 * 过程一:"抛":程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。
 *           并将此对象抛出。
 *           一旦抛出对象以后,其后的代码就不再执行。
 * 		关于异常对象的产生:① 系统自动生成的异常对象
 * 					 ② 手动的生成一个异常对象,并抛出(throw)
 * 过程二:"抓":可以理解为异常的处理方式:① try-catch-finally  ② throws
 * 二、try-catch-finally的使用
 * try{
 * 		//可能出现异常的代码
 * }catch(异常类型1 变量名1){
 * 		//处理异常的方式1
 * }catch(异常类型2 变量名2){
 * 		//处理异常的方式2
 * }catch(异常类型3 变量名3){
 * 		//处理异常的方式3
 * }
 * ....
 * finally{
 * 		//一定会执行的代码
 * }
 * 说明:
 * 1. finally是可选的。
 * 2. 使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象
 *    的类型,去catch中进行匹配
 * 3. 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出当前的
 *    try-catch结构(在没有写finally的情况)。继续执行其后的代码
 * 4. catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
 *    catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则,报错
 * 5. 常用的异常对象处理的方式: ① String  getMessage()    ② printStackTrace()
 * 6. 在try结构中声明的变量,再出了try结构以后,就不能再被调用
 * 7. try-catch-finally结构可以嵌套
 * 体会1:使用try-catch-finally处理编译时异常,是得程序在编译时就不再报错,但是运行时仍可能报错。
 *     相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。
 * 体会2:开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了。
 *      针对于编译时异常,我们说一定要考虑异常的处理。
 */
public class ExceptionTest1 {
	@Test
	public void test2(){
		try{
			File file = new File("hello.txt");
			FileInputStream fis = new FileInputStream(file);
			int data = fis.read();
			while(data != -1){
				System.out.print((char)data);
				data = fis.read();
			}
			fis.close();
		}catch(FileNotFoundException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	@Test
	public void test1(){
		String str = "123";
		str = "abc";
		int num = 0;
		try{
			num = Integer.parseInt(str);
			System.out.println("hello-----1");
		}catch(NumberFormatException e){
//			System.out.println("出现数值转换异常了,不要着急....");
			//String getMessage():
//			System.out.println(e.getMessage());
			//printStackTrace():
			e.printStackTrace();
		}catch(NullPointerException e){
			System.out.println("出现空指针异常了,不要着急....");
		}catch(Exception e){
			System.out.println("出现异常了,不要着急....");
		}
		System.out.println(num);
		System.out.println("hello-----2");
	}
}
-------------------------------------------throws----------------------------------------------
package com.atguigu.java1;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
 * 异常处理的方式二:throws + 异常类型
 * 1. "throws + 异常类型"写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。
 *     一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常
 *     类型时,就会被抛出。异常代码后续的代码,就不再执行!
 * 2. 体会:try-catch-finally:真正的将异常给处理掉了。
 *        throws的方式只是将异常抛给了方法的调用者。  并没有真正将异常处理掉。  
 * 3. 开发中如何选择使用try-catch-finally 还是使用throws?
 *   3.1 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果
 *       子类重写的方法中有异常,必须使用try-catch-finally方式处理。
 *   3.2 执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws
 *       的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。
 */
public class ExceptionTest2 {
	public static void main(String[] args){
		try{
			method2();
		}catch(IOException e){
			e.printStackTrace();
		}
//		method3();
	}
	public static void method3(){
		try {
			method2();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void method2() throws IOException{
		method1();
	}
	public static void method1() throws FileNotFoundException,IOException{
		File file = new File("hello1.txt");
		FileInputStream fis = new FileInputStream(file);
		int data = fis.read();
		while(data != -1){
			System.out.print((char)data);
			data = fis.read();
		}
		fis.close();
		System.out.println("hahaha!");
	}
}

62.java异常2:

-----------------------------------------------自定义异常--------------------------------------------
package com.atguigu.java2;
/*
 * 如何自定义异常类?
 * 1. 继承于现有的异常结构:RuntimeException 、Exception
 * 2. 提供全局常量:serialVersionUID
 * 3. 提供重载的构造器
 * 
 */
public class MyException extends Exception{
	static final long serialVersionUID = -7034897193246939L;
	public MyException(){	
	}
	public MyException(String msg){
		super(msg);
	}
}
--------------------------------------------练习-------------------------------------------------
package com.atguigu.java2;
public class StudentTest {
	public static void main(String[] args) {
		try {
			Student s = new Student();
			s.regist(-1001);
			System.out.println(s);
		} catch (Exception e) {
//			e.printStackTrace();
			System.out.println(e.getMessage());
		}
	}
}
class Student{
	private int id;
	public void regist(int id) throws Exception {
		if(id > 0){
			this.id = id;
		}else{
//			System.out.println("您输入的数据非法!");
			//手动抛出异常对象
//			throw new RuntimeException("您输入的数据非法!");
//			throw new Exception("您输入的数据非法!");
			throw new MyException("不能输入负数");
			//错误的
//			throw new String("不能输入负数");
		}
	}
	@Override
	public String toString() {
		return "Student [id=" + id + "]";
	}
}
-----------------------------------------练习2--------------------------------------------------
package com.atguigu.exer;
/*
 * 编写应用程序EcmDef.java,接收命令行的两个参数,要求不能输入负数,计算两数相除。
	对数据类型不一致(NumberFormatException)、缺少命令行参数(ArrayIndexOutOfBoundsException、
  	除0(ArithmeticException)及输入负数(EcDef 自定义的异常)进行异常处理。
提示: 
	(1)在主类(EcmDef)中定义异常方法(ecm)完成两数相除功能。
	(2)在main()方法中使用异常处理语句进行异常处理。
	(3)在程序中,自定义对应输入负数的异常类(EcDef)。
	(4)运行时接受参数 java EcmDef 20 10   //args[0]=“20” args[1]=“10”
	(5)Interger类的static方法parseInt(String s)将s转换成对应的int值。
        如:int a=Interger.parseInt(“314”);	//a=314;
 */
public class EcmDef {
	public static void main(String[] args) {
		try{
			int i = Integer.parseInt(args[0]);
			int j = Integer.parseInt(args[1]);
			int result = ecm(i,j);
			System.out.println(result);
		}catch(NumberFormatException e){
			System.out.println("数据类型不一致");
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println("缺少命令行参数");
		}catch(ArithmeticException e){
			System.out.println("除0");
		}catch(EcDef e){
			System.out.println(e.getMessage());
		}
	}
	public static int ecm(int i,int j) throws EcDef{
		if(i < 0 || j < 0){
			throw new EcDef("分子或分母为负数了!");
		}
		return i / j;
	}
}
-----------------------------------------------特殊情况----------------------------------------------
package com.atguigu.java1;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.junit.Test;
/*
 * try-catch-finally中finally的使用:
 * 1.finally是可选的
 * 2.finally中声明的是一定会被执行的代码。即使catch中又出现异常了,try中有return语句,catch中有
 * return语句等情况。
 * 3.像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,我们需要自己手动的进行资源的
 *   释放。此时的资源释放,就需要声明在finally中。
 */
public class FinallyTest {
	@Test
	public void test2(){
		FileInputStream fis = null;
		try {
			File file = new File("hello1.txt");
			fis = new FileInputStream(file);
			int data = fis.read();
			while(data != -1){
				System.out.print((char)data);
				data = fis.read();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if(fis != null)
					fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	@Test
	public void testMethod(){
		int num = method();
		System.out.println(num);
	}
	public int method(){
		try{
			int[] arr = new int[10];
			System.out.println(arr[10]);
			return 1;
		}catch(ArrayIndexOutOfBoundsException e){
			e.printStackTrace();
			return 2;
		}finally{
			System.out.println("我一定会被执行");
			return 3;
		}
	}
	@Test
	public void test1(){
		try{
			int a = 10;
			int b = 0;
			System.out.println(a / b);
		}catch(ArithmeticException e){
			e.printStackTrace();
//			int[] arr = new int[10];
//			System.out.println(arr[10]);
		}catch(Exception e){
			e.printStackTrace();
		}
//		System.out.println("我好帅啊!!!~~");
		finally{
			System.out.println("我好帅啊~~");
		}
	}
}
上一篇:USACO Section 2.4: The Tamworth Two


下一篇:Java编程的逻辑 (87) - 类加载机制