java(四)

来源:互联网 发布:网络电视机顶盒连接图 编辑:程序博客网 时间:2024/05/29 02:03
object:所有类的根类。
object是不断抽取而来的,具备所有对象都具有的共性内容。
常用的共性功能:
1.equals(Object obj):判断两个对象是否相等。(比的是地址值,不是内容)
  要判断具体内容就要覆盖此方法,根据对象特有内容,建立判断对象是否相同的依据。
   class Person extends Object
   {
private int age;
Person(int age)
{
this.age=age;
}
public boolean equals(Object obj)         //equals判断的是地址,这里覆盖后,判断的就是年龄。
{
if(!(obj instanceof Person))             //健壮性判断
{
throw new RuntimeException("类型错误");
}
Person p=(Person)obj;
return this.age==p.age;
}
   }
   class ObjectDemo
   {
public static void main(String[] args) 
{
Person p1=new Person(20);
Person p2=new Person(20);
/*ObjectDemo d=new ObjectDemo();        //用这两行,就等于用两个不同的类在比较年龄,编译不报错,运行时显示类型错误。
* System.out.println(p1.equals(d));
*/
System.out.println(p1.equals(p2));
}
   }


2.hashCode()  返回该对象的哈希码值。

3.getClass()  返回此Object的运行时类。就是当前对象所属字节码文件对象。
  比如上面例子中Person p1和p2所属的字节码文件都是Person.class
4.toString()   返回该对象的字符串表示形式。








异常(Exception)
异常是在程序运行时期发生的不正常情况。
在java中用类的形式对不正常情况进行了描述和封装对象。描述不正常的情况的类,就称为异常类。
以前正常流程代码和问题处理代码相结合,现在将正常流程代码和问题处理代码分离,提高了阅读性。
其实异常就是java通过面向对象的思想将问题封装成了对象,用异常类对其进行描述。不同问题用不同类进行具体的描述。
比如数组的角标越界,空指针等。问题很多,描述的类也很多,将其共性向上抽取,就形成了异常体系。


最终问题(不正常情况)就分成了两大类:
Throwable(可抛出性):无论是Error还是Exception,问题发生就应该抛出,让调用者知道并进行处理。
                      该体系的特点就在于Throwable及其所有的子类都具有可抛出性。
        可抛性到底指的是什么呢?怎么体现可抛性呢?
答:其实是通过两个关键字来体现的:throws和throw
凡是可以被这两个关键字所操作的类和对象都具有可抛性。
1.一般不可处理的: Error 
    error是由jvm抛出的严重性的问题,这种问题一般不针对性处理,直接修改程序。  
2.可以处理的: Exception
    
该体系的特点:子类的后缀名都是用其父类名做为后缀,阅读性很强。




如果异常在java中没有定义过(比如负数角标),就按照java异常的创建思想,面向对象,将负数异常就行描述,并封装成对象。
这种自定义的问题描述称为自定义异常。
注意:如果让一个类成为异常类,必须要继承异常体系,因为只有异常体系的子类才具有可抛性。
      才能被throws和throw这两个关键字操作。


异常的分类:
1.编译时被检测异常,只要是Exception和其子类都是,除了特殊子类RuntimeException体系。
        这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。
这样的问题都可以针对性处理。
2.编译时不检测异常(运行时异常),就是Exception中的RuntimeException和其子类。
这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的或者引发了内部状态的改变导致的。
这样的问题一般不处理,编译直接通过,在运行时,强制停止程序,让调用者对代码进行修改。
所以自定义异常时,要么继承Exception,要么继承RuntimeException。


throw和throws的区别:
1.throws使用在函数上
  throw使用在函数内。
2.throws抛出的是异常类,可以抛出多个,用逗号隔开。
  throw抛出的是异常对象。


异常处理的一种方式:声明
class FuShuIndexException extends Exception                            //自定义异常必须要继承异常体系,因为只有异常体系的子类才具有可抛性。
{
FuShuIndexException(String msg)
{
super(msg);                                                        //父类Exception已经有带信息的函数,直接调用就行。
}
}
class Demo
{
public int method(int arr[],int index) throws FuShuIndexException               //自定义异常要用throws声明在函数上,里面的封装了看不见,这里才能看见
{
if(index>=arr.length)
{
throw new ArrayIndexOutOfBoundsException("脚标越界:"+index);           //这个异常java中有,不用再声明
}
if(index<0)
{
throw new FuShuIndexException("脚标不能为负数:"+index);
}
return(arr[index]);
}
}
class ExceptionDemo
{
public static void main(String[] args) throws FuShuIndexException              //这里也一样,把自定义异常声明出来
{
int[] arr=new int[]{3,5,9};
Demo d=new Demo();
int num=d.method(arr,-2);
System.out.println("num="+num);
}
}


异常处理的另一种形式:捕捉,这是可以对异常进行针对性处理的方式。
格式:三个代码块
try
{  
 //这里面写的是需要被检测异常的代码。
}
catch(异常类 变量)    //该变量用于接收发生异常的对象
{   
 //处理异常的代码
}
finally
{         
 //一定会被执行的代码
}
注意:抛出异常时,多个异常直接写在throw后面,用逗号隔开。
      多catch时,父类的catch一定要放在最下面。否则,编译失败。




异常处理的几条原则:
1.函数内部如果抛出需要检测的异常,那么函数上必须要声明。
  或者必须在函数内用trycatch捕捉,否则,编译失败。
2.如果调用到了声明异常的函数,要么trycatch要么throws,否则,编译失败。
3.什么时候catch?什么时候throws?
  答:功能内部可以解决,用catch。
      解决不了,用throws告诉调用者,由调用者解决。
4.一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性处理。
 内部有几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。


finally里面的语句,无论程序是否有异常,都会执行。(除非在catch里用System.exit()语句退出了程序)
通常用于关闭(释放)资源。


try catch finally代码块组合:
1.try catch finally
2.try catch(多个)    当没有必要资源需要释放时,可以不用定义finally。
3.try finally     异常无法直接catch处理,但是资源需要关闭,就用try finally组合。






关于自定义异常,异常转换的一个例子:
/*需求:毕老师用电脑讲课
 *涉及到的对象:毕老师,电脑
 *分析其中的问题:
 *比如电脑蓝屏,冒烟。 
 * */
class LanPingException extends Exception
{
LanPingException(String msg)
{
super(msg);
}
}
class MaoYanException extends Exception
{
MaoYanException(String msg)
{
super(msg);
}
}
class NoPlanException extends Exception
{
NoPlanException(String msg)
{
super(msg);
}
}
class Computer
{
private int state=2;              //定义state表示电脑的状态,0表示正常,1表示蓝屏,2表示冒烟。
public void run()throws LanPingException,MaoYanException          //别忘了声明这两个异常。
{
if(state==1)
{
throw new LanPingException("电脑蓝屏啦!!!");
}
if(state==2)
{
throw new MaoYanException("电脑冒烟啦!!!");
}
System.out.println("电脑运行");
}
public void Reset()                //电脑重启的函数
{
state=0;
System.out.println("电脑重启!");
}
}
class Teacher
{
private String name;
private Computer comp;
Teacher(String name)
{
this.name=name;
comp=new Computer();             //计算机老师一产生,就要有电脑,就把它写在构造函数里
}  

public void prelect()throws NoPlanException         //老师讲课的函数,由于里面冒烟的catch用到了throw,所以就要声明
{
try
{
comp.run();
System.out.println(name+"讲课");
}
catch(LanPingException e)
{
System.out.println(e.toString());      //给出异常的类型与性质,这样就知道程序具体运行到哪了,到底什么异常,蓝屏还是冒烟
comp.Reset();  //处理蓝屏的方式就是重启,调用class Computer的Reset方法即可。
prelect();  //重启之后继续讲课,调用讲课方法。
}
catch(MaoYanException e)
{
System.out.println(e.toString());//给出异常的类型与性质
test(); //冒烟就上不了课了,先做练习等一会。
// throw e;                //把冒烟这件事告诉公司,抛出去,那这句话所在的函数(prelect函数)就得声明
//这里其实并不应该抛出冒烟异常,公司是软件培训公司,它也不会修电脑,所以应该抛出一个公司能解决的问题。
//冒烟会导致课程进度计划无法完成,这才是公司能处理的异常,这就是异常转换!!!!!!
throw new NoPlanException("课时进度无法完成,原因:"+e.getMessage());
//异常转换:捕捉到的是冒烟异常,但是抛出的是公司能处理的进度不能完成的异常。
}
}
public void test()
{
System.out.println("大家先做练习。");
}
}
class ExceptionTest
{
public static void main(String[] args) 
{
Teacher t=new Teacher("毕老师");
try
{
t.prelect();
}
catch(NoPlanException e)
{
System.out.println(e.toString()+".....");
System.out.println("换人");
}
}
}


异常的注意事项:
1.子类在覆盖父类方法时,父类的方法如果抛出了异常,
  那么子类的方法只能抛出父类的异常或者该异常的子类。
2.如果父类抛出多个异常,那么子类只能抛出父类异常的子集。


简单说:子类覆盖父类,只能抛出父类的异常或者子集。
注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try。

非RuntimeException异常类或者其子类的的异常都要声明捕捉。 只有RuntimeException 或者是其子类的异常是不需要进行声明捕捉的。



练习题:

写出程序结果。
1.
interface A{}
class B implements A
{
public String func()
{
return "func";
}
}
class Demo 
{
public static void main(String[] args)
{
A a=new B();            //关于多态知识,忘了就看笔记day10
a.func();               //编译看左边,运行看右边
System.out.println(a.func());
}
}




2.
class Fu
{
boolean show(char a)
{
System.out.println(a);
return true;
}
}
class Demo extends Fu
{
public static void main(String[] args)
{
int i=o;
Fu f=new Demo();
Demo d=new Demo;     
for(f.show('A');f.show('B')&&(i<2);f.show('C'))
{                //由于覆盖,所以f.show('A')运行子类的show方法。
//f.show('B')&&(i<2)    双与逻辑运算符有一个为假则为假,f.show('B')返回false,所以直接为假,后面都不用看了,直接结束了。
i++;
d.show('D');
}
}
boolean show(char a)
{
System.out.println(a);
return false;
}
}




3.
interface A{}
class B implements A
{
public String test()
{
return "yes";
}
}
class Demo
{
static A get()
{
return new B();
}
public static void main(String[] args)
{
A a=get();       //这句等于A a=new B;
System.out.println(a.test());   //编译看左边,运行看右边,与第一题同理。
}
}




4.
class Super
{
int i=0;
public Super(String a)
{
System.out.println("A");
i=1;
}
public Super()
{
System.out.println("B");
i+=2;
}
}
class Demo extends Super
{
public Demo(String a)
{
//  注意这里有一句隐藏的super();   忘了为啥看day09
System.out.println("C");
i+=5;
}
public static void main(Sreing[] args)
{
int i=4;
Super d=new Demo("A");      
System.out.println(d.i);
}
}




5.补全代码
interface Inter
{
void show(int a,int b);
void func();
}
class Demo
{
public static void main(String[] args)
{
//补全代码:调用两个函数,要求用匿名内部类。
}
}




6.写出程序结果
class TD
{
int y=6;
class Inner
{
static int y=3;
void show()
{
System.out.println(y);
}
}
}
class TC
{
public static void main(String[] args)
{
TD.Inner ti=new TD().new Inner();
ti.show();
}
}




7.选择题,写出错误原因。
class Demo
{
int show(int a,int b){return 0;}
}
下面那些函数可以存在于Demo的子类中。
A.public int show(int a,int b){return 0;}
B.private int show(int a,int b){return 0;}
C.private int show(int a,long b){return 0;}
D.public short show(int a,int b){return 0;}
E.static int show(int a,int b){return 0;}




8.写出程序结果
class Fu
{
int num=4;
void show()
{
System.out.println("showFu");
}
}
class Zi extends Fu
{
int num=5;
void show()
{
System.out.println("showZi");
}
}
class T
{
public static void main(String[] args)
{
Fu f=new Zi();
Zi z=new Zi();
System.out.println("f.num");  //成员变量编译运行都看左边
System.out.println("z.num");  
f.show();                     //成员函数编译看左边,运行看右边
z.show();
}
}




9.补全C类的代码,通过show函数打印两个数和
interface A
{
void show();
}
interface B
{
void add(int a,int b);
}
class C implements A,B
{
//程序代码
}
class D
{
public static void main(String[] args)
{
C c=new C();
c.add(4,2);
c.show();
}
}






10.写出程序结果
class Demo
{
public static void main(String[] args)
{
try
{
showExce();
System.out.println("A");        //对比13题做一下
}
catch(Exception e)
{
System.out.println("B");
}
finally
{
System.out.println("C");
}
System.out.println("D");
}
public static void showExce()throws Exception
{
throw new Exception;
}
}






11.写出程序结果
class Super
{
int i=0;
public Super(String s)
{
i=1;
}
}
class Demo extends Super
{
public Demo(String S)
{
i=2;
}
public static void main(String[] args)
{
Demo d=new Demo("yes");
System.out.println("d.i");
}

}




12.写出程序结果
class Super
{
public int get(){return 4;}
}
class Demo extends Super
{
public long get(){return 5;}
public static void main(String[] args)
{
Super s=new Demo();
System.out.println(s.get());
}
}




13.写出程序结果
class Demo
{
public static void func()
{
try
{
throw new Exception();
System.out.println("A");
}
catch(Exception e)
{
System.out.println("B");
}
}
public static void main(String[] args)
{
try
{
func();
}
catch(Exception e)
{
System.out.println("C");
}
System.out.println("D");
}
}




14.选择题
class  Demo
{
public void func()
{
//位置1;
}
class Inner{}
public static void main(String[] args)
{
Demo d=new Demo();
//位置2;
}
}
A.在位置1写new Inner();
B.在位置2写new Inner();
C.在位置2写new d.Inner();
D.在位置2写new Demo.Inner();






15.写出程序结果
class Exc0 extends Exception{}
class Exc1 extends Exc0{}
class Demo
{
public static void main(String[] args)
{
try
{
throw new Exc1;
}
catch(Exception e)
{
System.out.println("Exception");
}
catch(Exc0 e)
{
System.out.println("Exc0");
}
}
}






16.补全代码
interface Test
{
void func();
}
class Demo
{
public static void main(String[] args)
{
//补全代码:(匿名内部类)
}
void show(Test t)
{
t.func();
}
}






17.写出程序结果
class Test
{
public static String output="";
public static void foo(int i)
{
try
{
if(i==1);
throw new Exception;
output+="1";
}
catch(Exception e)
{
output+="2";
return;
}
finally
{
output+="3";
}
output+="4";
}
public static void main(String[] args)
{
foo(0);
System.out.println(output);
foo(1);
System.out.println(output);
}
}






18.建立一个图形接口,声明一个面积函数。圆形和矩形都实现这个接口,并得出两个图形的面积。
注意:体现面向对象的特征,对数值进行判断。用异常处理,不合法的数值要出现“这个数值是非法的”提示,不再进行运算。










19.写出程序结果
public class Demo
{
private static int j=0;
private static boolean mathodB(int k)
{
j+=k;
return true;
}
private static boolean mathodA(int i)
{
boolean b;
b=i<10|methodB(4);               //单或和双或的区别,忘了看day02

b=i<10||methodB(8);                 
}
public static void main(String[] args)
{
mathodA(0);
System.out.println(j);
}
}
















答案:  1.编译失败
2.A 
 B
3.编译失败
4.B
 C
 7
5.匿名内部类前提得有父类或者接口,这题若没有interface接口,也可以用object
 Inter in=new inter()        //因为要调用两个方法所以给他起个名字。
 {                          //这其实也是多态,多态本质是父类类型指向子类对象。Inter in是接口(父类),而匿名内部类new Inter()的实质就是匿名子类对象。
  public void show(int a,int b)
{}
public void func()
{}
  };
  in.show(3,4);
  in.func;
6.编译失败。非静态内部类中不能定义静态成员。
7.A.public int show(int a,int b){return 0;}
  可以,覆盖了
  B.private int show(int a,int b){return 0;}
  不可以,权限不够
  C.private int show(int a,long b){return 0;}
  可以,子类特有方法
  D.public short show(int a,int b){return 0;}
  不可以,调用的不确定性
  E.static int show(int a,int b){return 0;}
  不可以,静态只能覆盖静态。
 8.4
   5
   showZi
   showZi
 9.首先,覆盖两个接口中的方法。想用show打印x+y,局部变量生命周期很短,一运行完就弹栈了,
            所以不能直接在show方法里输出x+y.把他放在堆内存里,也就是对象中,就可以了
   private int x,y;
   public void add(int x,int y)
   {
 this.x=x;
 this.y=y;
   }
   public void show()
   {
 System.out.println("this.x+this.y");    //这里的this可以省略
   }
 10.B
    C
    D         //问题已经通过catch解决了,所以程序继续运行,输出D。
 11.编译失败。   Demo的构造函数第一句是隐藏的Super();   父类没有空参构造函数,所以编译失败。
 12.编译失败。   父类是int类型的方法,子类是long类型的,会出现调用的不确定性。
 13.编译失败。   输出A是废话,永远执行不到,所以报错。这和第十题不同,第十题的异常封装在了另一个方法里,看不到,不知道有没有异常,虽然也执行不到,但是不会报错。
 14.A.在位置1写new Inner();         //可以
    B.在位置2写new Inner();         //不可以,主函数是静态的,只能调用静态成员,所以内部类也必须是static才行。
    C.在位置2写new d.Inner();       //不可以,格式错误。d=new Demo(),所以题目的代码相当于new new Demo().Inner();    正确的应该是:new Demo().new Inner();
    D.在位置2写new Demo.Inner();    //不可以。格式是对的,但是Inner必须是静态的才对。
 15.编译失败。  多catch时,父类的catch要放在最后面。
 16.先要调用show方法,主函数是静态的,不能直接调用,创建对象。
    new Demo().show(new Test()
    {
public void func(){}
    });
 17.134
    13423 //output是静态字符串变量,所以底下还能用


18.
interface Areable
{
public double getArea();    //图形的面积要定义成double型。具体怎么求是子类的事,所以这里不用传参数(长,宽,半径)。
}
class NoValueException extends RuntimeException
{
NoValueException()
{
super();
}
NoValueException(String message)
{
super(message);
}
}
class Rec implements Areable
{
private int length;
private int width;
Rec(int length,int width)         //这里就没必要再声明了,因为这里如果出现异常,没必要再继续运行main函数下面的部分了,所以继承RuntimeException,出现异常,程序直接停掉,不用再计算area。
{
if(length<=0||width<=0)
{
throw new NoValueException("这个数值是非法的");
}
this.length=length;
this.width=width;
}
public double getArea()
{
return length*width;
}
}
class Circle implements Areable
{
private int radius;
public static final double PI=3.14;
Circle(int radius)
{
if(radius<=0)
throw new NoValueException("这个半径数值是非法的"); 
this.radius=radius;
}
public double getArea()
{
return radius*radius*PI;          
}
}
class Test
{
public static void main(String[] args)
{
Rec r=new Rec(3,5);
double a=r.getArea();
System.out.println("area="+a);
Circle c=new Circle(-1);
double area=c.getArea();
System.out.println("area="+area);
}
}
19.4

0 0
原创粉丝点击