黑马程序员--Java基础之面向对象二

 

知识提纲

1,抽象

2,接口

3,多态

4,内部类(匿名)

5,异常

6,包

 

1、抽象

1.1、抽象的定义

        抽象就是从多个事物中将共性的,本质的内容抽取出来。

        例如:狼和狗共性都是犬科,犬科就是抽象出来的概念。

1.2、抽象类

         Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。

        抽象类的由来:

        多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。

        例如:狼和狗都有吼叫的方法,可是吼叫内容是不一样的。所以抽象出来的犬科虽然有吼叫功能,但是并不明确吼叫的细节。

1.3、抽象类的特点

        1、抽象类和抽象方法必须用abstract关键字来修饰。

        2、抽象方法只有方法声明,没有方法体,定义在抽象类中。

        格式:修饰符abstract返回值类型  函数名(参数列表);

        3、 抽象类不可以被实例化,也就是不可以用new创建对象。原因如下:

        抽象类是具体事物抽取出来的,本身是不具体的,没有对应的实例。例如:犬科是一个抽象的概念,真正存在的是狼和狗。

        而且抽象类即使创建了对象,调用抽象方法也没有意义。

        4、抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则该子类也是抽象类。

/*
练习
员工类:name  id  pay
经理类:继承了员工类,并有自己特有的bonus
*/

class Employee
{
 private String name;
 private String id;
 private double pay;

 Employee(String name,String id,double pay)
 {
  this.name=name;
  this.id=id;
  this.pay=pay;
 }
 public abstract void work();

}

class pro extends Employee
{
 pro (String name,String id,double pay)
 {
  super(name,id,pay);
 }

 public void work()
 {
  System.out.println("pro work");
 }

}

class Manage extends Employee
{
 private int bonus;
 Manage(String name,String id,double pay,int bonus)
 {
  super(name,id,pay);
  this.bonus=bonus;

 }
 public void work()
 {
  System.out.println("manage work");
 }

}注:抽象类中可以有非抽象的方法。

抽象类和一般类没有太大不同
该怎样描述事物就怎样描述事物,只是,该事物出现一些看不懂的东西
这些不确定的部分,也是该事物的功能,需要明确出现,但是无法定义主体
通过抽象方法来表示

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

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

abstract class Student
{
 abstract void study(); //抽象方法,能继承,不能实例化
}

class BaseStudent extends Student
{
 void study()
 {
  System.out.println("base study");
 }
}

class AdvStudent extends Student
{
 void study()
 {
  System.out.println("adv  study");
 }
}

class AbstractDemo
{
 public static void main(String[] args)
 {
  System.out.println("Hello World!");
 }
}
1.4、抽象类与一般类的区别

        1、抽象类和一般类没有太大的不同。该如何描述事物,还是如何描述事物。只不过,该事物中出现了一些不知道具体内容的方法部分。这些不确定的部分,也是该事物的功能,需要明确出来,但是无法定义主体。通过抽象方法来表示。

        2、抽象类比一般类多了个抽象函数。就是在类中可以定义抽象方法。

        3、抽象类不可以实例化。

        4、抽象类虽然不能创建对象,但是也有构造函数。供子类实例化调用。

注:1、被abstract修饰的函数不能同时被privatefinalstatic修饰。

      原因:

                final:被final修饰的类不能有子类。而被abstract修饰的类一定是一个父类。

                private:抽象类中的私有的抽象方法,不被子类所知,就无法被复写。

                           而抽象方法出现的就是需要被复写。

                static:如果static可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了。

                            可是抽象方法运行没意义。

        2、抽象有一个特殊的地方:抽象类中可以不定义抽象方法。这样做可以不让本来实例化,也可以用于模块设计。

/*
月饼的制作;;;思想最重要

需求:获取一段程序的运行时间
原理:获取程序开始和结束的时间并相减即可

获取时间: System.currentTimeMillis();

当代码完成优化后,就可以解决这类问题

这中方式叫做 模板方法设计模式

什么是模板方法呢?
就是在定义功能时,功能的一部分是确定的,但有一部分是不确定的,而确定的部分在使用不确定的部分,
那么这时将不确定的部分暴露出去,由该类的子类去完成
*/

abstract class GetTime
{
 public final void getTime()
 {
  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 i=0;i<4000 ;i++ )
  {
   System.out.print("i="+i);
  }
 }
}

class  TemplateDemo
{
 public static void main(String[] args)
 {
  //GetTime get=new GetTime();
  SubTime sub=new SubTime();
  sub.GetTime();
  //get.getTime();
 }
}
2、接口

2.1、概述:接口,可以被认为是一个特殊的抽象类。当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。接口使用interface来表示,子类中用implements实现。格式为:

         interface 接口名{}  

        子类名 implements接口名{}

格式特点:

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

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

               常量:public static final

               方法:public abstract

        3、接口中的成员都是public的。

在使用中,常量可以不写publicstatic final,方法可以不写publicabstract,编译时Java会自动添加这些修饰符,因为这是固定的格式修饰符。但为了方便阅读,通常我们都写上。

2.2、特点

        1、接口是对外暴露的规则。

        2、接口是程序的功能扩展。

        3、接口的出现降低耦合性。

        4、接口可以用来多实现。这也是对多继承不支持的转换形式。java支持多实现。

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

        6、 接口与接口之间可以有继承关系。而且可以多继承。

注:1、接口不可以创建对象的,因为有抽象方法。需要被子类实现(implements),子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类是一个抽象类。

        2、实现多个接口时,接口中不可以有返回不同类型的同名抽象函数。这样子类实现时将不能复写

2.3、接口与抽象类

共性:都是不断向上抽取出来的抽象的概念。

       区别:

                1、抽象类体现继承关系,一个类只能单继承。

                    接口体现实现关系,一个类可以多实现。同时接口与接口之间有继承关系。

                2、抽象类是继承,是 "is a "关系。

                    接口是实现,是 "like a"关系。

                3、抽象类中可以定义非抽象方法,供子类直接使用。

                    接口的方法都是抽象,接口中的成员都有固定修饰符。

                4、抽象类中可以私有变量或方法。

                    接口中的常量和方法都是public修饰的权限。

/*
接口:初期理解,可以认为是一个特殊的抽象类
 当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示
class用于定义类
interface 用于定义接口

接口定义时,格式特点:
1、接口中常见定义:  常量,抽象方法
2、接口中的成员都有固定修饰符
 常量:public static final
 方法:public abstract
总结:接口中的成员都是public 的

接口;是不可以创建对象的,因为有抽象方法
需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实例化
否则子类是一个抽象类

接口可是被类多实现,也是对多继承不支持多转换形式,java支持多实现

java可以实现多继承,但是只在接口中实现

*/

interface Inter
{
 //int NUM=3; //这样也可以,会自动添加
 //void show();

 public static final int NUM=3;
 public abstract void show();
}

interface InterA
{
 public abstract void method();
}

class Demo
{
 public void function(){}
}

class Test extends Demo implements Inter,InterA //实现接口,类是继承,接口全是抽象,实现
{
 public void show(){}
 public void method(){}

}

interface A
{
 void methodA();
}

interface B //extends A
{
 void methodB();
}

interface C extends B,A
{
 void methodC();
}

class C implements C
{
 public void methodA(){}
 public void methodB(){}
 public void methodC(){}
}
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);

 }
}
3、多态
多态:可以理解为事物存在的多种体现形态

动物:猫,狗

猫 X=new 猫();
动物 x=new 猫();

3.1、多态的体现
 父类的引用指向了自己的子类对象
 父类的引用也可以接收自己的子类对象

3.2、多态的前提
 必须是类与类之间有关系,要么继承,要么实现
 还有一个前提,存在覆盖
3.3、多态的好处
 多态的出现大大的提高了程序的扩展性

3.4、多态的弊端
 提高了扩展性,但是只能使用父类的引用访问父类中的成员

3.5、多态的应用

3.6、多态的出现代码中的特点(多态使用的注意事项)

abstract class Animal
{
 public abstract void Eat();
}

class Cat extends Animal
{
 public void Eat()
 {
  System.out.println("Eat Fish!");
 }
 public void CatchMouse()
 {
  System.out.println("抓老鼠");
 }
}

class Dog extends Animal
{
 public void Eat()
 {
  System.out.println("吃骨头");
 }
 public void KanJia()
 {
  System.out.println("看家");
 }
}

class Pig extends Animal
{
 public void Eat()
 {
  System.out.println("饲料");
 }
 public void GongDi()
 {
  System.out.println("拱地");
 }
}
class DuoTaiDemo2
{
 public static void main(String[] args)
 {
  
  //Animal a=new Cat(); //类型提升  向上转型,
  //a.Eat();

  //如果想要调用猫的特有方法(抓老鼠)时,如何操作?
  //强制将父类的引用,转成子类类型
  //Cat c=(Cat)a; //向下转型
  //c.CatchMouse();

  //千万不要出现这杨的操作,就是将父类对象转成子类类型
  //我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换
  //多态至始至终都是子类对象在做着变化
  
  //Animal a = new Animal();
  //Cat c = (Cat)a;
  Function(new Dog());
  Function(new Cat());
 }

 public static void Function(Animal a) //Animal a=new Cat();
 {
  a.Eat();
  if(a instanceof Cat)
  {
   Cat c =(Cat)a;
   c.CatchMouse();
  }
  else if(a instanceof Dog)
  {
   Dog d=(Dog)a;
   d.KanJia();
  }
 }

}
3.7、在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败
在运行时期:参阅对象所属的类是否有调用的方法

总结:成员函数在多态调用时,编译看左边,运行看右边

在多态中,成员变量的特点:
无论编译和运行,看左边

在多态中,静态成员函数的特点:
无论编译和运行,看左边

class Fu
{
 int num=5;
 void method1()
 {
  System.out.println("fu_method_1");
 }
 void method2()
 {
  System.out.println("fu_method_2");
 }
 static void method4()
 {
  System.out.println("fu_method_4");
 }
}

class Zi extends Fu
{
 int num=8;
 void method1()
 {
  System.out.println("zi_method_1");
 }
 void method3()
 {
  System.out.println("zi_method_3");
 }
 static void method4()
 {
  System.out.println("zi_method_4");
 }

}
class  DuoTaiDemo4
{
 public static void main(String[] args)
 {
  //Fu f=new Zi();
  //System.out.println(f.num);
  
  //Zi z=new Zi();
  //System.out.println(z.num);

  //f.method1();
  //f.method2();
  //f.method3();

  Fu f=new Zi();
  f.method4();

  //Zi z=new Zi();
  //z.method1();
  //z.method2();
  //z.method3();
 }
}
3.8多态的应用

        1、定义好工具类,即将共同行为封装在一个类中。

        2、对类型进行抽取,---->多态的产生。

        3、操作同一父类型,对其中的子类型均可操作

/*
需求:
电脑运行实例
电脑运行基于主板
*/

interface PCI
{
 public void open();
 public void close();
}

class MainBoard
{
 public void run()
 {
  System.out.println("mainboard run");
 }
 public void usePCI(PCI p) //PCI p=new NetCard();
 {
  if(p!=null)
  {
   p.open();
   p.close();
  }
 }
}
class NetCard implements PCI
{
 public void open()
 {
  System.out.println("netcard run");
 }
 public void close()
 {
  System.out.println("netcard close");
 }
}

class SoundCard implements PCI
{
 public void open()
 {
  System.out.println("soundcard run");
 }
 public void close()
 {
  System.out.println("soundcard close");
 }
}
/*
class MainBoard
{
 public void run()
 {
  System.out.println("mainboard run");
 }
 public void useNetCard(NetCard c)
 {
  c.open();
  c.close();
 }
}

class NetCard
{
 public void open()
 {
  System.out.println("netcard open");
 }
 public void close()
 {
  System.out.println("netcard close");
 }
}
*/

class DuoTaiDemo5
{
 public static void main(String[] args)
 {
  MainBoard mb=new MainBoard();
  mb.run();
  mb.usePCI(new NetCard());
  mb.usePCI(new SoundCard());
 }
}
4,内部类

4.1、概述

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

        当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物的内容。如定义一个描述人的类,而手、心脏等都属于人,然它们又有自己的功能描述,这时可以在人这个描述类中,定义一个描述心脏的类,也就是内部类。

        编译时,如果代码中有内部类,生成的class文件中会含有这样的文件:Test$1.class。编译器将会把内部类翻译成用$(美元符号)分隔外部类名和内部类名的常规类文件。这是内部类的一种编译现象。

/*
内部类的访问规则
1、内部类可以直接访问外部类中的成员,包括私有
 之所以可以直接访问外部类中的成员,是因为内部类中持有一个外部类的引用,格式  外部类名.this
2、外部类要访问内部类,必须建立内部类对象
 直接访问内部类,注意格式  Outer.Inner in=new Outer().new Inner();

当内部类在成员位子上,就可以被成员修饰符所修饰
 比如: private  static   // private class Inner
注意静态类只能访问静态成员,当内部类被static修饰后,只能直接访问外部类中的static成员,出现访问局限
 
 当外部其他类中,如何直接访问static内部类的非静态成员呢
 new Outer.Inner().Function();

 在外部其他类中,如何直接访问static内部类的静态成员呢?
 Outer.Inner.Function();
注意:当内部类中定义了静态成员,该内部类必须是static的
   当外部类中的静态方法访问内部类时,内部类也必须是static

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

class Body //内部类封装,不能直接访问,但提供了方法可以访问
{
 private class heart
 {

 }
 public void show()
 {
  new heart();
 }

}
*/

class Outer //外部类
{
 private int num=5;

 static class Inner //内部类,内部类可以用private 修饰
 {
  //int num=10;
  void Function()
  {
  // int num=15;
   //num=15, this.num=10; outer.this.num=5;
   System.out.println("inner class"+Outer.this.num);
  }
 }

 class Inner2
 {
  void show()
  {
   System.out.println("inner2 class");
  }
 }

 public void method()
 {
  Inner i=new Inner();
  i.Function();

 }
}

class  InnerClassDemo
{
 public static void main(String[] args)
 {
  //Outer o=new Outer();
  //o.method();
  //直接访问内部类,注意格式  Outer.Inner in=new Outer().new Inner();
  Outer.Inner in=new Outer().new Inner();
  in.Function();
  // new Outer.Inner().Function();

 }
}
4.2、匿名内部类

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

        2、定义匿名内部类的前提:

             内部类必须是继承一个类或者实现接口。

             特殊情况:因为所以的类都有一个父类Object,所以在定义时也可以用Object

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

        4、其实匿名内部类就是一个匿名子类对象。可以理解为带内容的对象。

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

匿名内部类的利与弊:

        好处:简化书写

        弊端:1、不能直接调用自己的特有方法、

                     2、不能做强转动作。

                     3、如果继承的父类或接口中有很多方法时,使用匿名内部类阅读性会非常差,且调用会很麻烦。所以匿名内部类中定义的方法有一般不超过3个。


interface Inter
{
 void method();
}

class Test
{
 //使用匿名内部类方法
 /*
 static class Inner implements Inter
 {
  public void method()
  {
   System.out.println("method run");
  }
 }*/
 static Inter function()
 {
  return new Inter()
  {
   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();
 }
}

5,  异常

5.1、概述

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

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

        3、程序可能出现的错误或问题

                a、用户输入错误导致的异常:如用户不正常使用程序,输入一些非法参数

                b、设备硬件等发生的错误:如硬盘损坏等

                c、物理限制:如存储空间不足等

                d、代码错误:在程序编写的方法可能不正确,返回错误参数等。

5.2、异常体系

       有两种对问题的划分方式:

              一种是严重的问题;

              一种是非严重的问题。

        对于严重的问题,java通过Error类进行描述。对Error类一般不编写针对性的代码对其进行处理。

        对于非严重的,java通过Exception类进行描述。对于Exception可以使用针对性的处理方式进行处理。

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

这也就构成了Java的异常体系:

        Throwable

|---Error //通常出现重大问题如:运行的类不存在或者内存溢出等。

                |---Exception //运行时出现的一起情况

                            |---R       untimeException    //特殊异常类,抛时不需要声明

        ExceptionError的子类名都是以父类名作为后缀。

异常体系的特点:

       1、异常体系中的所有类以及建立的对象都具备可抛性。

         2、也就是说可以被throwthrows关键字所操作。

        3、只有异常体系具备这个特点。

5.3、异常有两种:

        1、编译时被检测异常

             该异常在编译时,如果没有处理(没有抛也没有try),编译失败。该异常被标识,代表着可以被处理。

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

              在编译时,不需要处理,编译器不检查。该异常的发生,建议不处理,让程序停止。需要对代码进行修正。如:RuntimeException以及其子类。

5.4、 异常的处理

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

        try

        {

                 需要被检测的代码。

        }

        catch(异常类  变量)

        {

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

        }

        finally

        {

                一定会执行的语句;

        }

有三个结合格式:

        atry

             {

             }

             catch ()

             {

             }

        btry

             {

             }

             finally

             {

             }

        ctry

             {

             }

             catch ()

             {

             }

             finally

             {

             }

注意:

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

        2)如果在一个功能中,定义了一些必须要执行的代码,可以用try{}finally{}的方式,将一定执行的代码放在finally代码块中。

        3finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。

2throwthrows的用法

        throw定义在函数内,用于抛出异常对象。

        throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。

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

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

3、调用者对抛出信息的处理

        当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。要么在内部try catch处理。要么在函数上声明让调用者处理。

        一般情况下,函数内出现异常,函数上需要声明。在功能上通过throws的关键字声明了该功能有可能会出现异常类型。

特殊之处:

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

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

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

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

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

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

        String getMessage();//获取异常的信息。返回字符串。

        toString();//获取异常类名和异常信息,返回字符串。

        printStackTrace();//获取异常类名和异常信息,以及异常出现在程序中的位置.返回值void.

                                //其实JVM默认的异常处理机制,就是在调用printStackTrace方法,打印异常的堆栈的跟踪信息。

        printStackTrace(PrintStream s)//通常用该方法将异常内容保存在日志文件中,以便查阅。

5.5、自定义异常

       因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对这些特有的问题可以按照java中的面向对象思想。将特有的问题,进行自定义的异常封装。定义类继承Exception或者RuntimeException

        1,为了让该自定义类具备可抛性。

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

这就叫做自定义异常。

       当自定义了异常类继承Exception后,如果未在类中定义异常信息,那么通过toString方法打印出来的结果就只有自定义的异常类名,不会显示异常信息。那么应该如何定义异常信息呢?

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

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

注:自定义异常:

                必须是自定义类有继承关系,通常继承Exception

        继承Exception原因:

                异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。

                只有这个体系中的类和对象才可以被throwsthrow操作。

/*

项目中会出现特有的问题
对于一些特有的问题进行自定义的异常封装

自定义异常

需求:在a/b中,b不能等于零和小于零

当在函数内部出现throw抛出异常对象,那么就必须要给对应处理动作
1  用try catch 处理
2、在函数上声明让调用者处理

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

定义异常信息
自定义异常必须继承Exception
原因:因为异常和异常对象都有可抛性

throws和throw的区别
 throws使用在函数上
 thro使用在函数内

 throws后面根的是函数上
throw定义在函数内
*/

class FuShuException extends Exception
{
 private String msg;
 FuShuException(String msg)
 {
  this.msg=msg;
 }
 public String getMessage()
 {
  return msg;
 }
}

class Demo
{
 int div(int a,int b)throws FuShuException
 {
  if(b<0)
   throw new FuShuException("除数出现负数"); //手动通过throw抛出自定义异常
  return a/b;
 }
}
class ExceptionDemo3
{
 public static void main(String[] args) //throws Exception
 {
  Demo d=new Demo();
  try
  {
   int x=d.div(4,-1);
   System.out.println("x=="+x);
  }
  catch (FuShuException e)
  {
   System.out.println("出现负数");
   System.out.println(e.getMessage()); //by zero
   System.out.println(e.toString());
   e.printStackTrace(); //异常名称,异常信息,异常出现的位子
         //其实jvm默认的异常处理机制,就是在调用printStackTrace方法
  }
  System.out.println("over");
 }
}

5.6、异常的好处与原则

好处:

1、将问题进行封装。

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

原则:

        1、处理方式有两种:try或者 throws

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

        3、多个catch时,父类的catch放到最下面。否则编译会报错,因为其余的catch语句执行不到。

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

5.7、异常的注意事项

        1、问题在内部被解决就不需要声明。

        2catch是用于处理异常。如果没有catch就代表异常没有被处理,如果该异常是检测时异常。那么必须声明。

        3、在子父类覆盖时:

              a,子类抛出的异常必须是父类的异常的子类或者子集。

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

/*

Exception中有一个特殊的子类异常RuntimeException 运行时异常
在函数内抛出该异常,函数上不用声明,编译通过

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

对于异常分两种:
1、编译时被检测的异常

2、编译时不被检测的异常,(运行时异常,RuntimeException及其子类)

*/
class Demo
{
 int div(int a,int b)throws Exception
 {
  if(b<0)
   throw new Exception("被负数除了");
  if(b==0)
   throw new ArithmeticException("被零除了"); //手动通过throw抛出自定义异常
  return a/b;
 }
}
class ExceptionDemo4
{
 public static void main(String[] args)
 {
  Demo d=new Demo();
  try
  {
   int x=d.div(4,-1);
   System.out.println("x=="+x);
  }
  
  catch (ArithmeticException e)
  {
   System.out.println("出现负数");
   System.out.println(e.getMessage()); //by zero
   System.out.println(e.toString());
   e.printStackTrace(); //异常名称,异常信息,异常出现的位子
         //其实jvm默认的异常处理机制,就是在调用printStackTrace方法
  }
  System.out.println("over");
 }
}

//异常练习

/*
练习:有一个圆形和长方形
都可以获取面积,对于面积如果出现非法的数值,视为是获取面积出现问题
问题通过异常来表示
现有对这个程序进行基本设计

*/

class NoValueException extends RuntimeException
{
 NoValueException(String message)
 {
  super(message);
 }
}

interface Shape
{
 void getArea();
}
class Rec implements Shape
{
 private int len,wid;
 Rec(int len,int wid)//throws NoValueException
 {
  if(len<=0 || wid<=0)
   throw new NoValueException("出现非法值");

  this.len=len;
  this.wid=wid;
 }
 public void getArea()
 {
  System.out.println(len*wid);
 }
}

class Circle implements Shape
{
 private int radius;
 public static final double PI=3.14;
 Circle(int radius)
 {
  if(radius<=0)
   throw new RuntimeException("非法值");
  this.radius = radius;
 }
 public void getArea()
 {
  System.out.println(radius*radius*PI);
 }

}
class  ExceptionTest1
{
 public static void main(String[] args)
 {

  Rec r=new Rec(3,4);
  r.getArea();

  Circle c = new Circle(-5);
  c.getArea();

  /*
  try
  {
   Rec r=new Rec(-3,4);
   r.getArea();
  }
  catch (NoValueException e)
  {
   System.out.println(e.toString());
  }*/
  System.out.println("over");
 }
}
6. 

6.1、package

        在java中,管叫包,相当于文件夹。包里通常存放的是类文件,因为我们在编写程序的时候,难免会有类名相同的情况,就如我们人名一样。为了对类进行分类管理,java就有了包的出现,在不同包中可以有相同的类名,调用的时候连同包名一起就行。

        包也是一种封装形式。在包中可以有很多类文件,但是只提供一个类文件,供外界使用。

6.2包的作用

        1、为避免多个类重名的情况,如果出现两个相同名字的类,可通过包将两者区分,从而避免冲突。

        2、对类文件进行分类管理,可以将相关的一些类放在同一个包中。

        3、给类提供多层命名空间,如a包中的Demo.class文件,如果要创建Demo对象,就要在使用时加上a.如:a.Demo demo=new a.Demo();

        4、包的出现可以将java的类文件和源文件相分离。

6.3、则     

        1、包必须写在程序的第一行。因为要先有包,才知道类文件的存放地方。

        2、类的全称:包名.类名。

        3、编译定义了包的程序文件时,在编译时要指定包的存储目录。

       如:javac –d c:\mypack类名.java

6.4、包之间的访问     

        1、要访问其他包中的类,需要定义类的全称:包名.类名。

        2、包如果不在当前路径,需要使用classpath设定环境变量,为JVM指明路径。

        3、被访问的包中的类权限必须是public的。

        4、类中的成员权限:public或者protectedprotected是为其他包中的子类提供的一种权限。类公有后,被访问的成员也要公有才可以被访问。不同包中的子类可以直接访问父类中被protected权限修饰的成员。同一个包中,protected只作用为覆盖。

6.5、包的导入——import

        1、可以简化类名。在调用其他包中的类时,需要写类的全称,也就是连同包名一起书写。当类存在多层包中时,如:haha.hehe.pack.Demo,使用import导入后,使用其类时,就可以不加包名了。导入格式如:import haha.hehe.pack.Demo;

        2、一个程序文件中只有一个package,可以有多个importimport导入的是包中的类,不导入包中的包。

        3、注意事项:

               a,在导入包时,如果包中有很多类,可以使用通配符 *来替代包中的所有类。但是,建议不要使用通配符 *,因为将不需要使用的类导入后,会占用内存空间。所有在编写程序时,要使用包中的哪些类,就导入哪些类。

               b,定义包名不要重复,可以使用url来完成定义,url是唯一的。如:package cn.itheima.Demo

               c,导入的不同包中有相同类时,必须写类的全名以区分,否则将报错

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值