『黑马程序员』第二话<面向对象>


◤5.1-5.2◢      面向对象的概念

    1.面向对象的三个特征:封装 、继承、多态

    2.举些生活中面向对象的例子。思路:应该结合面向过程来回答此题。

◤5.3◢           类和对象的关系

    1. 类是一种对事物的描述

    2.对象是指由这描述生产出来的实体。

例如:汽车图纸是类,由图纸制造出来的汽车就是对象。

c是一个类型为Car的变量。

                                 

◤5.4◢ 成员变量与局部变量

作用范围:成员变量作用于整个类中

                局部变量作用于函数中,或者语句中。

内存中的位置:

                    成员变量:在堆内存中,因为对象的存在,才在内存中存在

    局部变量,存在栈内存中。        

◤5.5◢匿名对象

       与有名对象的区别:

例如:new Car().num=5;  但没办法做后继操作了,这就是与有名对象的区别

       什么时候使用:

当对对象的方法只使用一次。

例:Car c=new Car();  show (c);  

                show(new Car());   //没办法再对这个对象再进行操作

◤5.6◢封装

  概念:     是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

  好处:    将变化隔离
           便于使用
  提高重用性
  提高安全性

◤5.7◢private修饰符

private:私有修饰符:用于修饰类中的成员(成员变量,成员函数)。
                     私有只在本类中有效

变量私有化以后,类以外即使建立了对象也不能直接访问,需要在类中提供对应访问方式。

    注意:私有仅仅是封装的一种表现形式。


    之所以对外提供访问方式,就因为可以在访问方式中加入逻辑判断等语句。
    对访问的数据进行操作,提高代码健壮性
 

一般有private 会有 set(){}和 get(){}

◤5.8◢构造函数

与一般函数的不同点:

格式:类名(){}  //不用定义返回值,所以不可以写return

运行方式:一般函数是要调用才执行,一个对象可以调用多次

     构造函数是一创建对象就执行,给对象进行初始化操作,每建立一个对象会执行且只执行一次

        什么时候定义构造函数?

当事物肯定具备一些特性或行为时,我们就可以将这些内容定义在构造函数内

◤5.9◢构造代码块

格式: {   }//直接一个大括号,里面有执行语句

构造代码块优先于构造函数

构造代码块与构造函数的区别:

个类中可以有很多重载的构造函数时,创建一个对象时便会有不执行的构造函数,

但构造代码块是无论创建什么对象,都会执行一次。


◤5.10-5.11◢this关键字

用途:区分同名的局部变量和成员变量

this代表的是谁?谁调用就代表谁。

需求:给人定义一个比较年龄是否相同的功能

public boolean compare (People p)

{

return this.age==p.age;

}

当定义类中的功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象,但凡本类功能内部使用了本类对象

◤5.12◢this在 构造函数间的互相调用

什么时候要用?  当一个类中的同名重载构造函数要互相调用时,不能用 类名();,而要用this();

注意:1.只用于同类中的构造函数中;   2 .只能放于第一行

◤6.1◢static 关键字

static 静态

用法:是一个修饰符,用于修饰成员(成员变量,成员函数

注意,修饰变量时一定要是成员变量,局部变量会报错

static修饰的成员可被类名调用,格式 : 类名.成员。

static修饰的成员特点:

1.随着类的加载而加载,也就是说会随着类的消失而消失,它的生命周期最长

    2.优先于对象存在

    3.被所有的对象所共享

    4.可以被类名所调用

实例变量(成员变量)与类变量(静态)的区别
1.存放位置
      类变量随着类的加载而存在于方法区中
      实例变量随着对象的建立而存在于堆内存中
2.生命周期
类变量随着类的消失而消失
实例变量随着对象消失而消失
静态使用注意事项:
   1.静态方法只能访问静态成员
    非静态方法能访问静态也能访问非静态
 
  2.静态方法中不可以定义this.super关键字
      因为静态优先于对象存在,所以静态方法中不可以出现this,静态方法在类一被加载时就进了方法区,此时还没有对象。
 
  3.主函数是静态
 静态有利有弊
                       利:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份
     
                    可以直接被类名调用。
 
                     弊:生命周期过长,访问出现局现性(静态虽好,只能访问静态)

                      什么时候使用静态
                              要从两方面下手:
                                 因为静态修饰的内容有成员变量和成员函数。
                       1.什么时候定义静态变量呢?
        当对象中出现共享数据时,该数据被静态所修饰
       对象中的特有数据要定义成非静态存在于堆内存中
       2.什么时候定义静态函数呢?
        当功能内部没有访问到非静态数据(对象特有数据)//因为静态只能访问静态
       那么该功能可能定义成静态函数

◤6.5◢帮助文档的制作  javadoc

格式:javadoc -d C:\myhelp -author -version ***.java
类必须是public 。

一个类中默认有一个空参数的构造函数,而且权限与所属类一样

◤6.6◢静态代码块

格式:static                                                 特点:随着加载而执行,只执行一次不管创建几个对象都只执行一次

{

执行语句;

}

执行顺序:静态代码块>>>>>构造代码块>>>>>>构造函数

Person p=new Person();

/*这句话都做了什么
        1.因为new用到了person.class.所以会先找到person.class文件并加载到内存中
2.执行该类中的static代码块,如果有的话,给person.class类进行初始化
3.在堆内存中开辟空间,分配内存地址
4.在堆内存中建立对象的特有属性,并进行默认初始化
5.对属性进行显示初始化
6.对对象进行构造代码块初始化
7.对对象进行对就的构造函数初始化

8.将内存地址付给栈内存中的p变量

◤6.8◢对象调用成员过程

                                                   

◤6.9-6.10◢单例设计模式-----饿汉式:解决一个类在内存中只存在一个对象

思路:1.为了避免其它程序过多建立该类对象,先禁止其它程序建立该类对象-------------------将构造函数私有化

     2.还为了让其他程序访问到该类对象,只好在本类中,自定义一个对象-------------------在类中创建一个本类对象

     3.为了方便其它程序对自定义对象的访问,可以对外提供一些访问方式--------------------提供一个方法可以获取到该对象

class Single-----------------------------------饿汉式
{
private Single(){}
private static Single s=new Single();
public static Single get()
{return s;}
}

class Single1----------------------------------懒汉式(延时加载)
{
private Single1(){};
private static Single1 s=null;
public static Single1 get()
{
if(s==null)
s=new Single1();
return s;

}
}
         重点:饿汉式和懒汉式有何不同?

1.饿汉式:Single类一加载进内存,就已经创建好了对象s

.懒汉式:对象的方法被调用时才初始化,也称延时加载,。single类进内存后,对象还没有存在,只有调                                    用get方法时,才建立对象

2.懒汉式存在安全问题,在多线程中懒汉式可能会出现两个对象,如果加个同步锁,则会使运行速度变慢

◤7.1-7.2◢继承

格式:类A  extends 类B

继承:1.提高了代码的复用性。
     2.让类与类之间产生了关系,有了这个关系才有了多态的特性

注意:

1.java中,继承只能单继承,不能多继承,因为存在安全问题:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一个。

但支持多层继承。

2.如何使用一个继承体系呢?想要使用体系先查阅体系父类的描述,因为你类中定义的是该体系中共性功能。
通过了解共性功能。就可以知道该体系的基本功能
那么这个体系已经可以基本使用了
那么在具体调用时,要创建最子类对象,因为有可能父类不能创建对象,创建子类对象可以使用更多的功能,包括基本的也包括特有的、
简单一句话:查阅父类功能,创建子类对象使用功能


◤7.3◢聚集:has a

聚合:球员和球队的关系,

组合:人和手的关系,相对较紧密

◤7.4-7.5◢子父类变量的特点 

如果子类中出现非私有的同名成员变量时,
子类要访问本类中变量用this
子类要访问父类中的同名变量,用super
如果子类与父类的变量或函数一样,子类覆盖父类

覆盖: 1.子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败
     
            2.静态只能覆盖静态
 
 注意:
 
          重载:只看同名函数的参数列表
   
         
 重写:子父类方法要一模一样

父类中成员特点
是否创建子类对象构造函数构造代码块静态代码块
执行执行执行
否,调用子类方法不执行不执行执行

.子父类中的构造函数。

在对子类对象进行初始化时,父类的构造函数也会运行

那是因为子类的构造函数默认第一行有一条隐式语句   super();

super() 会访问父类中的空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();

为什么子类一定要访问父类中的构造函数。

因为父类中的数据子类可以直接获取,所以子类对象在建立 时,需要先查看父类是如何对这些数据进行初始化的。

 

 注意:super()只能放第一行,this()也只能放第一行

 结论:子类的所有构造函数,默认都会访问父类中空参数的构造函数

 因为子类每个构造函数内的第一行都有一句隐式super()

 当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数

 子类中至少会有一个构造函数会访问父类中构造函数。

◤7.7◢final关键字

1.可以修饰 类 函数 变量

2.final修饰的类不能被继承,为了避免被子类复写功能

3.被final修饰的方法不能覆盖

4.被final修饰的变量是一个常量只能被赋值一次,既可以修饰成员变量,也可以修饰局部变量,变成常量

 当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便于阅读

 而这个值不需要改变,所以加上final修饰。作为常量:常量书写规范所有字母都大写,如果由多个单词组成。单词用_连接

5.内部类定义在类中的局部位置上时,只能访问局部被final修饰的局部变量

◤◢抽象类的特点:


1.抽象方法一定要在抽象类中

2.抽象方法和抽象类都必须被abstract修饰

3.抽象类不可以用new 创建对象,因为调用抽象方法没意义

4.抽象类中的方法要被使用,必须由子类复写所有的抽象方法后,建立子类对象调用

   如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。



 抽象类和一般类没有太大的不同。

 该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。

 这些不确定的部分,也是该事物的功能,需要明确出现,但是无法定义主体。

 通过抽象方法来表示。

 抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法,抽象类不可实例化



 特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

 ------------------------------------------------------------

 /*假如我们在开发一个系统时需要对员工进行建模,员工包含3个属性:

姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另外还有一个资金属性

请使用继承思想设计出员工类和经理类,要求类中提供必要的方法进行属性访问。

员工类(employee):name  id   pay   

经理类(manage) :继承员工,并有自己特有的bonus*/

class Employee

{

private String name;

private String id;

private double pay;

Employee(String name,String id,double pay) //--------------------------构造函数后面有类型的话,子类不能省略super()

{

this.name=name;

this.id=id;

this.pay=pay;

}

public abstract void work();  //-------------------------------------------注意格式

}

class Manager extends Employee

{

private int bonus;

Manager(String name,String id,double pay,int bonus)//-------------------------------必须有

{

super(name,id,pay);

this.bonus=bonus;

}

public void work()  -------------------------------------必须复写

{

System.out.println("MWK"); 

}

}

class AbstractTest 

{

public static void main(String[] args) 

{

Employee a=new Employee();

}

}

------------------------------------------------

/*

需求:获取一段程序运行时间

原理:获取程序开始和结束的时间并相减即可。

*/

abstract class GetTime

{

public final void getTime()//-----------------final修饰,为了不让覆盖

{

long start =System.currentTimeMillis();//-----------------------获取当前时间

runcode();

long end=System.currentTimeMillis();

System.out.println("毫秒:"+(end-start));

}

public abstract void runcode();//-------------------------抽象函数,让子类一定实现

}

class SubTime extends GetTime

{

public void runcode() //--------------------------------实现上面的抽象

{

for (int x=0;x<4000 ;x++ )

{

System.out.println(x);

}

}

}

class  gettime1

{

public static void main(String[] args) 

{

SubTime gt=new SubTime();

gt.getTime();

}

}

◤7.12-7.14◢接口


接口:初期理解,可以认为是一个特殊抽象类,当这抽象类只有抽象方法时,那么该类可以通过接口的形式表示。

interface用于定义接口

class 用于定义类

接口定义时,格式特点:

1.接口中常见定义:常量,抽象方法

2.接口中的成员都有固定修饰符

  常量:public static final

  方法:public abstract

  记住:接口中的成员都是public的

interface Inter

{

        public static final int NUM=3;

public abstract void show();//-----------------------接口中的方法是抽象方法

}

class Test implements Inter

{

public void show(){}   //---------------------------------必须复写

}

class InterfaceDemo

{

public static void main(String[] args)

 {

Test t=new Test();

System.out.println(t.NUM);

System.out.println(Test.NUM);

System.out.println(Inter.NUM);

 }

}

◤接口的特点◢

implements  实现关系

接口:是不可以创建对象的,因为有抽象方法

需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化

否则子类是一个抽象类。

-------------------

接口的特点:

接口与接口是继承关系

接口是对外暴露的规则

接口是程序的功能扩展

接口可以用来多实现

类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。

◤8.1-8.7◢多态

abstract class Animal

{

public abstract void eat();

public void show()

{System.out.println("8");}

}

class Cat extends Animal

{

public void eat()//----------------------子类实现父类时,权限一定要大于等于父类方法,而接口的方法有public,所以子类必须用public

{System.out.println("鱼");}

void catchMouse()

{System.out.println("鼠");}

}

class Dog extends Animal

{

public void eat()

{System.out.println("骨");}

void catchMouse()

{System.out.println("家");}

}

public class 多态 {

public static void main(String[] args) 

{

/*Animal a=new Cat();

a.eat();

Animal b=new Dog();

b.eat();*/

function(new Cat());//----------------这就是多态的表现:以后可以还有更多的动物,但只要再加个类,然后function(new  XX)就行

function(new Dog());

}

public static void function(Animal q)

{

q.eat();

}}

              多态的体现

父类引用指向了自己的子类对象

父类的引用也可以接收自己的子类对象,

多态的前提

必须有继承或实现关系

通常还有一个前提:存在覆盖

多态的好处

多态的出现大大提高扩展性

多态的弊端:

但是只能使用父类的引用访问父类中的成员

多态的应用

在多态中非静态成员函数的特点
1.在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有,编译失败
2.在运行时期:参阅对象所属的类中是否有调用的方法
编译是否成功看左边,运行时看右边的方法。
3..多态中成员变量的特点,都参考左边。
4.静态函数:编译运行都看左边。

1.子类实现父类时,权限一定要大于等于父类方法,而接口的方法有public,所以子类必须用public

interface PCI----------------------------------------------------接口
{
public void open();
public void close();
}
class MainBoard-----------------------------------主板一启用,就启用接口
{
public void run()
{
System.out.println("mainboard run");
}
public void usePCI(PCI p)
{
p.open();
p.close();
}
}
class NetCard implements PCI---------------------------------------所以主板一运行,网卡就运行
{
public void open()
{
System.out.println("net run");
}
public void close() 
{
System.out.println("net close");
}

}
public class 主态的主板例子 
{
public static void main(String[] args)
{
MainBoard mb=new MainBoard();
mb.run();
mb.usePCI(new NetCard());

◤8.8-8.9◢    Object类

           1.equals()       比较在内存中位置是否一致,如果一致返回true.

                                    用equals(Object obj){}重写方法,String中的equals()已复写过。

           2.toString()

内部类:

       将一个类定义在另一个类的里面,对里面那个类就成为内部类(内置类,嵌套类)。

◤9.1◢、内部类的访问规则:

 内部类可以直接访问外部类中的成员,包括私有

          之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this

 外部类要访问内部类,必须建立内部类对象

   访问格式:

 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。

 可以直接建立内部类对象。

  Outer.Inner in = new Outer().new Inner();

 

◤9.2◢  静态内部类

             当内部类在成员位置上,就可以被成员修饰符所修饰。

              比如:private:将内部类在外部类中进行封装。

              static:内部类就具备了static特性

              当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。

              在外部其他类中,如何访问内部类的非静态成员呢?

              new Outer.Inner().function(); 非静态

              在外部其他类中,如何直接访问static内部类的静态成员呢?

              Outer.Inner.function(); 静态

              注意:当内部类中定义了静态成员,该内部类必须是static的

                     当外部类中的静态方法访问内部类时,内部类也必须是static的。

 

◤9.3◢  内部类定义原则

当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事务在使用外部事物的内容。

 class Outer  
{  
       private int x = 3;  
        
       static class Inner//静态内部类   
       {  
              int x =4;  
              void function()  
              {  
                     int x = 6;  
                     System.out.println("Inner:"+Outer.this.x);//访问外部类时需要外部类的引用  
              }  
       }  
       void method()  
       {  
              Inner in = new Inner();  
              in.function();  
       }  
}  
   
class InnerClassDemo  
{  
       public static void main(String[] args)  
       {  
              new Outer.Inner().function();  
              //Outer out = new Outer();   
              //out.method();   
   
              //直接访问内部类中的成员   
              //Outer.Inner in = new Outer().newInner();//外部类名.内部类名 变量名 =外部对象.内部对象  
              //in.function();   
       }  

class Outer
{
       private int x = 3;
      
       static class Inner//静态内部类
       {
              int x =4;
              void function()
              {
                     int x = 6;
                     System.out.println("Inner:"+Outer.this.x);//访问外部类时需要外部类的引用
              }
       }
       void method()
       {
              Inner in = new Inner();
              in.function();
       }
}
 
class InnerClassDemo
{
       public static void main(String[] args)
       {
              new Outer.Inner().function();
              //Outer out = new Outer();
              //out.method();
 
              //直接访问内部类中的成员
              //Outer.Inner in = new Outer().newInner();//外部类名.内部类名 变量名 =外部对象.内部对象
              //in.function();
       }
}

5、内部类定义在局部时,(如内部类存在于外部类的方法中)

     1.不可以被成员修饰符修饰

       2..可以直接访问外部类中的成员,因为还持有外部类中的引用。

但是不可以访问它所在局部中的变量,只能访问被final修饰的局部变量。

 class Outer  
{  
       int x=3;  
       void method(final int a)  
       {  
              class Inner  
              {  
                     final int y = 4;//内部类只能访问被final修饰的局部变量   
                     void function()  
                     {  
                            System.out.println(a);  
                     }  
              }  
              new Inner().function();//调用Inner内部类时必须将其放在内部类的后面,方便JVM识别  
       }  
}  
   
class InnerClassDemo2  
{  
       public static void main(String[] args)  
       {  
              Outer out = new Outer();  
              out.method(7);  
     out.method(8);//这里程序能够正常运行,因为局部成员进栈运行完后,栈内存会被自动释放,因此可以重新定义局部成员的值   
       }  

class Outer
{
       int x=3;
       void method(final int a)
       {
              class Inner
              {
                     final int y = 4;//内部类只能访问被final修饰的局部变量
                     void function()
                     {
                            System.out.println(a);
                     }
              }
              new Inner().function();//调用Inner内部类时必须将其放在内部类的后面,方便JVM识别
       }
}
 
class InnerClassDemo2
{
       public static void main(String[] args)
       {
              Outer out = new Outer();
              out.method(7);
       out.method(8);//这里程序能够正常运行,因为局部成员进栈运行完后,栈内存会被自动释放,因此可以重新定义局部成员的值
       }
}

◤9.4◢、匿名内部类:

1.匿名内部类其实就是内部类的简写格式。

2.定义匿名内部类的前提:内部类必须是继承一个类或者实现接口

3.匿名内部类的格式: new 父类或者接口(){定义子类的内容}

4.其实匿名内部类就是一个匿名子类对象,而且这个对象有点“胖”,也可以理解为带内容的对象。

5.匿名内部类中定义的方法最好不要超过3个。

6.定义匿名内部类,就是为了简化书写,覆盖方法。
abstract class AbsDemo  
{  
       abstract void show();  
}  
class Outer  
{  
       int x = 3;  
       public void function()  
       {  
              new AbsDemo()  
              {  
                     voidshow()  
                     {  
                            System.out.println("x===="+x);  
                     }  
              }.show();  
       }  
   
}  
class InnerClassDemo3  
{  
       public static void main(String[] args)  
       {  
              new Outer().function();  
       }  

abstract class AbsDemo
{
       abstract void show();
}
class Outer
{
       int x = 3;
       public void function()
       {
              new AbsDemo()
              {
                     voidshow()
                     {
                            System.out.println("x===="+x);
                     }
              }.show();
       }
 
}
class InnerClassDemo3
{
       public static void main(String[] args)
       {
              new Outer().function();
       }
}分析:内部类都做了什么事情?

1.它继承了一个类

2.它进行了复写

3.创建对象

4.进行调用

new AbsDemo(){void show()}.show();

 


练习:
interface Inter  
{  
       void method();  
}  
class Test  
{  
       /* 
       static class Inner implements Inter 
       { 
              public void method() 
              { 
                     System.out.println("methodrun"); 
              } 
       } 
       */  
       //补足代码,使用匿名内部类   
       static Inter function()  
       {  
              return new Inter()//Inner   
              {  
                     public void method()  
                     {  
                            System.out.println("method run");  
                     }  
              };  
       }  
}  
   
class InnerClassTest  
{  
       public static void main(String[] args)  
       {  
              //Test.function():Test 类中有一个静态的方法function。   
              //.method():function这个方法运算后的结果是一个对象,而且是一个Inter类型的对象。   
              //因为只有是Inter类型的对象,才可以调用method方法。   
              Test.function().method();  
/* 
              Inter in = Test.function(); 
              in.method(); 
*/  
       }  

interface Inter
{
       void method();
}
class Test
{
       /*
       static class Inner implements Inter
       {
              public void method()
              {
                     System.out.println("methodrun");
              }
       }
       */
       //补足代码,使用匿名内部类
       static Inter function()
       {
              return new Inter()//Inner
              {
                     public void method()
                     {
                            System.out.println("method run");
                     }
              };
       }
}
 
class InnerClassTest
{
       public static void main(String[] args)
       {
              //Test.function():Test 类中有一个静态的方法function。
              //.method():function这个方法运算后的结果是一个对象,而且是一个Inter类型的对象。
              //因为只有是Inter类型的对象,才可以调用method方法。
              Test.function().method();
/*
              Inter in = Test.function();
              in.method();
*/
       }
}

◤9.5◢异常

 1、异常的体系

       Error:

       1.通常出现重大问题如:运行的类不存在或者内存溢出等。

       2.不编写针对代码对其处理

       Exception:

       1.在运行时出现的一些情况,可以通过try catch finally

Exception 和Error的子类名都是以父类名作为后缀。

异常:就是程序在运行时出现不正常情况。

异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现。

 

对于问题的划分为两种:一种是严重的问题,一种是非严重的问题。

对于严重的,java通过Error类进行描述。

       对于Error一般不编写针对性的代码对其进行处理。

对于非严重的,java通过Exception类进行描述。

       对于Exception可以使用针对性的处理方式进行处理。

无论Error或者Exception都具有一些共性内容。比如:不正常情况的信息,引发原因等。

Throwable
       Error
       Exception


◤9.6◢、异常的处理

java提供了特有的语句进行处理

try{

       需要被检测的代码

}

catch(异常类变量){

       处理异常的代码:(处理方式)

}

finally{

       一定会执行的语句;

}

 

3、对捕获到的异常对象进行常见方法操作

       StringgetdMessage();获取异常信息。

◤9.7◢    在函数上声明异常:

便于提高安全性,让调用者进行处理,不处理编译失败。

◤9.8◢对多异常的处理。

1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体。

2.对方声明几个异常,就对应有几个catch块。不要定义多余的catch块

如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面

建议在进行catch处理时,catch中一定要定义具体处理方式。

不要简单定义一句e.printStackTrace();也不要简单的就书写一条输出语句。

class Demo  
{  
       int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了该功能有可能会出现问题。  
       {  
              int[] arr = new int[a];  
              System.out.println(arr[4]);  
              return a/b;  
       }  
}  
   
class ExceptionDemo  
{  
       public static void main(String[] args) //throws Exception   
       {  
              Demo d = new Demo();  
              try  
              {  
                     int x = d.div(5,0);  
                     System.out.println("x="+x);  
              }  
              catch (ArithmeticExceptione)//Exception  e = newArithmeticException();  
              {  
                     System.out.println("除零了");  
                     //System.out.println(e.getMessage());// /by zero;   
                     System.out.println(e.toString());//异常名称:异常信息   
                     //e.printStackTrace();//异常名称,异常信息,异常出现的位置。   
                                          //其实JVM默认的异常处理机制,就是在调用printStrackTrace方法。  
                                          //打印异常的堆栈的跟踪信息。   
              }  
              catch(ArrayIndexOutOfBoundsException e)  
              {  
                     System.out.println(e.toString());  
                     System.out.println("角标越界啦!!");  
              }  
              System.out.println("over");  
       }  

class Demo
{
       int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
       {
              int[] arr = new int[a];
              System.out.println(arr[4]);
              return a/b;
       }
}
 
class ExceptionDemo
{
       public static void main(String[] args) //throws Exception
       {
              Demo d = new Demo();
              try
              {
                     int x = d.div(5,0);
                     System.out.println("x="+x);
              }
              catch (ArithmeticExceptione)//Exception  e = newArithmeticException();
              {
                     System.out.println("除零了");
                     //System.out.println(e.getMessage());// /by zero;
                     System.out.println(e.toString());//异常名称:异常信息
                     //e.printStackTrace();//异常名称,异常信息,异常出现的位置。
                                          //其实JVM默认的异常处理机制,就是在调用printStrackTrace方法。
                                          //打印异常的堆栈的跟踪信息。
              }
              catch(ArrayIndexOutOfBoundsException e)
              {
                     System.out.println(e.toString());
                     System.out.println("角标越界啦!!");
              }
              System.out.println("over");
       }
}

◤9.9◢、自定义异常:必须是自定义类继承Exception

因为项目中会出现特有问题,而这些问题并未被java锁描述并封装对象,所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题,进行自定义的异常封装。

当在函数内部出现了throw抛出异常对象时,那么就必须要给对应的处理动作,

要么在内部try catch处理;要么在函数上声明让调用者处理。

一般情况下,函数内出现异常,函数上需要声明。

发现打印的结果中只有异常的名称,却没有异常的信息,因为自定义的异常并未定义信息。

如何定义异常信息呢?

因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类通过super语句,那么就可以直接通过getMessage方法获取自定义的异常信息。

继承Exception原因:

异常体系有一个特点:因为异常类和异常对象都被抛出。

他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。只有这个体系中的类和对象才可以被throws和throw操作。

 

需求:在本程序中,对于除数是负数的,也视为是错误的是无法进行运算的,那么就需要对这个问题进行自定义描述。

[java] view plaincopyprint?class FuShuException extends Exception//自定义异常必须集成Exception体系  
{  
       private int value;  
       FuShuException(Stringmsg,int value)  
       {  
              super(msg);  
              this.value = value;  
       }  
       public int getValue()  
       {  
              return value;  
       }  
       /*private String msg; 
       FuShuException(Stringmsg) 
       { 
              this.msg = msg; 
       } 
       public String getMessage() 
       { 
              return msg; 
       } 
       */  
}  
class Demo  
{  
       int div(int a,int b)throws FuShuException//在功能上通过throws的关键字声明了该功能有可能会出现问题。  
       {  
              if(b<0)  
                     throw new FuShuException("出现了除数是负数的情况/ by fushu",b);//手动通过throw关键字抛出一个自定义异常。  
              return a/b;  
       }  
}  
class ExceptionDemo2  
{  
       public static void main(String[] args)  
       {  
              Demo d = new Demo();  
              try  
              {  
                     int x = d.div(4,-1);  
                     System.out.println("x="+x);  
              }  
              catch (FuShuException e)  
              {  
                     System.out.println(e.toString());  
                     System.out.println("出现错误的负数是:"+e.getValue());  
              }  
              System.out.println("over");  
       }  

class FuShuException extends Exception//自定义异常必须集成Exception体系
{
       private int value;
       FuShuException(Stringmsg,int value)
       {
              super(msg);
              this.value = value;
       }
       public int getValue()
       {
              return value;
       }
       /*private String msg;
       FuShuException(Stringmsg)
       {
              this.msg = msg;
       }
       public String getMessage()
       {
              return msg;
       }
       */
}
class Demo
{
       int div(int a,int b)throws FuShuException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
       {
              if(b<0)
                     throw new FuShuException("出现了除数是负数的情况/ by fushu",b);//手动通过throw关键字抛出一个自定义异常。
              return a/b;
       }
}
class ExceptionDemo2
{
       public static void main(String[] args)
       {
              Demo d = new Demo();
              try
              {
                     int x = d.div(4,-1);
                     System.out.println("x="+x);
              }
              catch (FuShuException e)
              {
                     System.out.println(e.toString());
                     System.out.println("出现错误的负数是:"+e.getValue());
              }
              System.out.println("over");
       }
}

◤9.10◢、throws和throw的区别:

1.throws使用在函数上;

2.throw使用在函数内;

3.throws后面跟的是异常类,可以跟多个,用逗号隔开;

4.throw后跟的是异常对象。

 


◤9.11◢、RuntimeException异常

Exception 中有一个特殊的子类异常RuntimeException运行时异常。

如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过。

如果在函数上声明了该异常,调用者可以不用进行处理。编译一样通过。

之所以不用在函数上声明,是因为不需要让调用者处理。当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,并对代码进行修正。

自定义异常时,如果该异常的发生,无法再继续进行运算,那么就让自定义异常继承RuntimeException

class FuShuException extendsRuntimeException  
{  
       FuShuException(Stringmsg)  
       {  
              super(msg);  
       }  
}  
   
class Demo  
{  
       int div(int a,int b)//throws ArithmeticException   
       {  
              if(b<0)  
                     thrownew FuShuException("除数出现负数了!");  
              else if(b==0)  
                     thrownew ArithmeticException("被零除啦!!");  
              return a/b;  
       }  
}  
   
class ExceptionDemo3  
{  
       public static void main(String[] args)  
       {  
              Demo d = new Demo();  
              int x = d.div(4,-1);  
              System.out.println("x="+x);  
   
              System.out.println("over");  
       }  
}  
   
/* 
class Person 

       public void checkName(String name) 
       { 
              if(name.equals("lisi"))//NullPointerException 
              if("lisi".equals(name))//if(name!=null && name.equals("lisi")) 
                     System.out.println("Yes"); 
              else 
                     System.out.println("No"); 
       } 

  
class TestException 

       public static void main(String[] args) 
       { 
              Person p = new Person(); 
              p.checkName(null); 
       } 

*/ 

class FuShuException extendsRuntimeException
{
       FuShuException(Stringmsg)
       {
              super(msg);
       }
}
 
class Demo
{
       int div(int a,int b)//throws ArithmeticException
       {
              if(b<0)
                     thrownew FuShuException("除数出现负数了!");
              else if(b==0)
                     thrownew ArithmeticException("被零除啦!!");
              return a/b;
       }
}
 
class ExceptionDemo3
{
       public static void main(String[] args)
       {
              Demo d = new Demo();
              int x = d.div(4,-1);
              System.out.println("x="+x);
 
              System.out.println("over");
       }
}
 
/*
class Person
{
       public void checkName(String name)
       {
              if(name.equals("lisi"))//NullPointerException
              if("lisi".equals(name))//if(name!=null && name.equals("lisi"))
                     System.out.println("Yes");
              else
                     System.out.println("No");
       }
}
 
class TestException
{
       public static void main(String[] args)
       {
              Person p = new Person();
              p.checkName(null);
       }
}
*/总结:

可处理的用Exception,不可处理的则用RuntimeException

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

◤10.1◢异常-finally

finally代码块:定义一定执行的代码,通常用于关闭资源

class FuShuException extends Exception  
{  
       FuShuException(String msg)  
       {  
              super(msg);  
       }  
}  
   
class Demo  
{  
       int div(int a,int b)throws FuShuException  
       {  
              if(b<0)  
                     throw new FuShuException("除数为负数");  
              return a/b;  
       }  
}  
   
class ExceptionDemo4  
{  
       public static void main(String[] args)  
       {  
              Demo d = new Demo();  
              try  
              {  
                     intx = d.div(3,-1);  
                     System.out.println("x="+x);  
              }  
              catch (FuShuException e)  
              {  
                     System.out.println(e.toString());  
                     return;  
              }  
              finally  
              {  
                     System.out.println("finally");//finally中存放的是一定会被执行的代码   
              }  
              System.out.println("over");  
       }  

class FuShuException extends Exception
{
       FuShuException(String msg)
       {
              super(msg);
       }
}
 
class Demo
{
       int div(int a,int b)throws FuShuException
       {
              if(b<0)
                     throw new FuShuException("除数为负数");
              return a/b;
       }
}
 
class ExceptionDemo4
{
       public static void main(String[] args)
       {
              Demo d = new Demo();
              try
              {
                     intx = d.div(3,-1);
                     System.out.println("x="+x);
              }
              catch (FuShuException e)
              {
                     System.out.println(e.toString());
                     return;
              }
              finally
              {
                     System.out.println("finally");//finally中存放的是一定会被执行的代码
              }
              System.out.println("over");
       }
}


◤10.2◢、异常处理语句的几种格式:

第一种格式:   
try{  
}  
catch (){  
}  
   
//第二种格式:   
try{  
}  
catch (){  
}  
finally{  
}  
   
//第三种处理格式:   
try{  
}  
finally{  
}  
//记住一点:catch是用于处理异常。如果没有catch就代表异常没有被异常处理过,   
//如果该异常时检测时异常,那么久必须声明。 


◤10.3◢、异常在子父类覆盖中的体现:

1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。

2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。

3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须要进行try处理,绝对不能抛。

◤10.5◢异常总结:

异常:是什么?是对问题的描述,将问题进行对象的封装。

异常体系:

       Throwable

             Error
             Exception
                 RuntimeException

             

异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性,也就是说可以被throw和throws关键字所操作。只有异常体系具备这个特点。

当函数内容有throw抛出异常对象,并为进行try处理,必须要在函数上声明。否则编译失败。

注意,RuntimeException除外,也就说,函数内如果抛出的RuntimeException异常,函数上可以不用声明。

如果函数声明了异常,调用者需要进行处理,处理方法可以throw,可以try

异常有两种:

       编译时被检测异常:

              该异常在编译时,如果没有处理(没有throw也没有try),编译失败。

              该异常被标识,代表这可以被处理。

 

       运行时异常(编译时不检测)

              在编译时,不需要处理,编译器不检查。

              该异常的发生,建议不处理,让程序停止,需要对代码进行修正。

注意:

1.finally中定义的通常是关闭资源代码,因为资源必须被释放。

2.只有当遇到System.exit(0);语句是,系统会退出,finally才不会被执行。

3.当catch语句中遇到return时,JVM会检查catch后有没有finally,如果有,则执行finally中的语句,然后退出;如果没有,则直接退出。

 

6、自定义异常:

       定义类继承Exception或者RuntimeException

       1.为了让该自定义类具备可抛性;

       2.让该类具备操作异常的共性方法。

       当要定义自定义异常的信息时,可以使用父类已经定义好的功能。

       将异常信息传递给父类的构造函数。

       classMyException extends Exception

       {

              MyException(String message)

              {

                     super(message);

              }

       }

自定义异常:是按照java的面向对象思想,将程序中出现的特有问题进行封装。

异常的好处:

       1.将问题进行封装;

       2.将正常流程代码和问题处理代码相分离,方便与阅读。

 

异常的处理原则:

       1.处理方式有两种:try或者throw。

       2.调用到抛出异常的功能时,抛出几个,就处理几个。一个try对应多个catch的情况。

       3.多个catch,父类的catch要放在最下面。

       4.catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句,也不要不写。当捕获到的异常,本功能处理不了时,可以继续在catch中抛出:

              try

              {

                     throw new AException();

              }

              catch (AException e)

              {

                     throw e;

              }

              如果该异常处理不了,但并不属于该功能出现的异常。

              可以将异常转换后,在抛出和该功能相关的异常。

              或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,

              让调用者知道,并处理,也可以将捕获异常处理后,转换型的异常。

              try

              {

                     throw new AException();

              }

              catch (AException e)

              {

                     //throwAException();对AException处理。

                     throw new BException();

              }

异常的注意事项:

       在子父类覆盖时:

       1.子类抛出的异常必须是父类的异常的子类或者子集;

       2.如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。

其实就是子类不能比父类抛出更多异常!

面试题:写出this关键字的含义,final有哪些特点?

this:代表本类对象,哪个对象调用this所在的函数,this就代表哪个对象。

final:

1.修饰类,变量(成员变量,静态变量,局部变量),函数。

2.修饰的类不可以被继承;

3.修饰的函数不可以被覆盖

4.修饰的变量时一个常量,只能赋值一次。

5.内部类只能访问局部变量中被final修饰的变量

 

◤10.7◢、包(package)

对类文件进行分类管理

给类提供多层命名空间

写在程序文件的第一行

类名的全称是:包名.类名

包也是一种封装形式。

 


jar包

       1.方便项目的携带。

       2。方便于使用,只要在classpath设置jar路径即可。

       3.数据库驱动,SSH框架等都是jar包体现的。

需要查看或者运行Jar包的时候,需要先将classpath路径设置成Jar包路径,

例如:setclasspath=c:\myclass\haha.jar

编译:javac -d 路径 类名.java

javac -d c:\myclass PackageDemo.java 或者javac -d . PackageDemo.java              中间的.是指当前路径

-d:指定包所存放的位置

运行:java 包名.类名

java pack.PackageDemo

 

◤10.8◢包与包之间访问

为了简化类名的书写,使用了一个关键字:import。

import导入的是包中的类。

建议不要写通配符*,需要用到包中的哪个类,就导入哪个类。

建议包名不要重复,可以使用url来完成定义,url是唯一的。

package pack;  
import packb.haha.hehe.heihei.*;  
class PackageDemo  
{  
       publicstatic void main(String[] args)  
       {  
              packa.DemoA d = new packa.DemoA();  
              d.show();  
   
              //packb.DemoB d = new packb.DemoB();   
              //d.method();   
       }  

package pack;
import packb.haha.hehe.heihei.*;
class PackageDemo
{
       publicstatic void main(String[] args)
       {
              packa.DemoA d = new packa.DemoA();
              d.show();
 
              //packb.DemoB d = new packb.DemoB();
              //d.method();
       }
}

错误原因:packa包不在当前目录下

需要设置classpath,告诉jvm去哪里找指定的packa包。

有了包,范围变大,一个包中的类要被访问,必须要有足够大的权限,所以被访问的的类要被public修饰

类共有后,被访问的成员也要共有才可以被访问。

总结:

       包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。

       不同包中的子类还可以直接访问父类中被protected权限修饰的成员

包与包之间可以使用的权限只有两种:public protected

                            public            protected        default           private

同一个类中           ok                  ok                         ok                  ok

同一个包中           ok                  ok                         ok

子类                       ok                  ok

不同包中               ok

 

注意:当想建立一个包中的两个不同类而防止在编译的时候被覆盖,这里可以将另一个类在新建的java文档里添加同名包名,这样编译的时候就不会覆盖原始类产生的class文件。

 

◤10.9◢、导入import

为了简化类名的书写,使用一个关键字,import;

例如:import packb.haha.hehe.heihei.DemoC;


◤10.10◢、Jar包

1、Java的压缩包

1.方便项目的携带;

2.方便于使用,只要在classpath设置jar路径即可;

3.数据库驱动,SSH框架等都是以jar包体现的。

 

2、如何创建jar包?

格式:jar -cfxx.jar 包名,前提是需要切换到打包路径中,且路径中已经存在相应包文件

jar -cf haha.jar packa pack

 

3、jar命令常见用法:

-c:创建新的归档文档;

-f:指定归档文件名

-t:列出归档目录

-v:在标准输出中生成详细输出

当使用jar命令打包程序后,jar包文件中会有一个配置清单文件

设置jar包的classpath路径方式为setclasspath=c:\myclass\haha.jar

将jar包中的详细信息写入硬盘中的一个文件里,操作如下:

jar -tf a.jar >c:\1.txt


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值