COREJAVA第四章

第四章、 面向对象(下)

Ø 类的继承

Ø 抽象类

Ø 接口

Ø 对象的多态性

Ø 异常

Ø 

Ø 访问控制

Ø JAVA的命名规范

一、类的继承

类具有继承性,子类对父类的继承关系体现了现实世界中特殊和一般的关系。通过继承可以更有效地组织程序结构,明确类间关系,并充分利用已有的类来完成更复杂、深入的开发。

(1)继承类定义的格式

class <子类> extends <唯一的父类名>

{

   <类定义体>

}

(2)继承类的特点

Ø 通过继承可以简化类的定义

例:

Person.java类

class Person {

public String name;

public int age;

public Person(String name,int age){

this.name=name;

this.age=age;

}

public Person() {

//如果不写这个构造函数,看看对类Student有什么影响。

}

public void getInfo() {

System.out.println(name);

System.out.println(age);

}}

Student.java类

class Student extends Person{

public void study(){

System.out.println("Studding");

}

public static void main(String[] args){

Person p=new Person();

p.name="person";

p.age=30;

p.getInfo();

Student s=new Student();

s.name="student";

s.age=16;

s.getInfo();

s.study();

}

}

Ø Java只支持单继承,不允许多重继承。

例:

class A{

}

class B{

}

class C extends A{

}

class C extends B {//不允许

}

Ø 可以有多层继承,即一个类可以继承某一个类的子类,如类B继承了类A,类C又可以继承类B,那么类C也间接继承了类A。 

例:

class A{

}

class B extends A{

}

class C extends B{

}

Ø 子类继承父类所有的成员变量和成员方法,但不继承父类的构造方法。在子类的构造方法中可使用语句super(参数列表) 调用父类的构造方法。

例:

class Student extends Person

{

 public Student(String name,int age,String school){

 super(name,age);//调用父类

 的构造方法

 this.school=school;

 }

}

Ø 如果子类的构造方法中没有显式地调用父类构造方法,也没有使用this关键字调用重载的其它构造方法,则在产生子类的实例对象时,系统默认调用父类无参数的构造方法。 

例:

   public class B extends A

   {

   public B()

   {

   super();//有没有这一句效果都是一样的。

   }

   }

(3)子类对象的实例化

Ø 通过new关键字产生对象,对类中的成员变量进行初始化赋值。

Ø 绑定构造方法参数,就是new 类名(实际参数列表)中所传递进的参数赋值给构造方法中的形式参数变量。

Ø 如有this()调用,则调用相应的重载构造方法被调用的重载构造方法的执行流程结束后,回到当前构造方法。

Ø 显式或隐式追溯调用父类的构造方法,父类的构造方法的执行流程结束后,回到当前构造方法,当前构造方法继续往下执行。

Ø 进行实例变量的显式初始化操作,也就是执行在定义成员变量时就对其进行赋值的语句。

Ø 执行当前构造方法的方法体中的程序代码 。

(4)覆盖父类的方法

Ø 覆盖方法必须和被覆盖方法具有相同的方法名称、参数列表和返回值类型。

Ø 如果在子类中想调用父类中的那个被覆盖的方法,我们可以用super.方法的格式 。

Ø 覆盖方法时,不能使用比父类中被覆盖的方法更严格的访问权限 。

 

    当子类的成员变量与父类的成员变量同名时,子类的成员变量会隐藏父类的成员变量;当子类的方法与父类的方法同名,参数列表、返回值类型相同时,子类的方法将覆盖父类的方法。

(5)final关键字

Ø 在Java中声明类、属性和方法时,可使用关键字final来修饰。

Ø final标记的类不能被继承。

Ø final标记的方法不能被子类重写。

Ø final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次。

Ø final标记的成员变量必须在声明的同时或在该类的构造方法中显式赋值,然后才能使用。

Ø 方法中定义的内置类只能访问该方法内的final类型的局部变量,用final定义的局部变量相当于是一个常量,它的生命周期超出方法运行的生命周期,将一个形参定义成final也是可以的,这就限定了我们在方法中修改形式参数的值。 

Ø public static final共同标记常量时,这个常量就成了全局的常量。且这样定义的常量只能在定义时赋值,即使在构造函数里面也不能对其进行赋值。 

二、抽象类

(1)什么是抽象类?

在一个类中只有方法的定义,而没有方法的实现,这样的方法称为抽象方法,含有抽象方法的类称为抽象类。

(2)抽象方法定义格式

abstract 返回值类型 抽象方法(参数列表);

(3)抽象类定义格式

abstract   class  类名(abstractClass){ 

/* 类定义体 */

}

(4)抽象类定义规则

Ø 抽象类必须用abstract关键字来修饰;抽象方法也必须用abstract来修饰。

Ø 抽象类不能被实例化,也就是不能用new关键字去产生对象。

Ø 抽象方法只需声明,而不需实现。

Ø 含有抽象方法的类必须被声明为抽象类,抽象类的子类必须覆盖所有的抽象方法后才能被实例化,否则这个子类还是个抽象类。

例:

abstract class A{

   abstract int aa(int x,int y);

   }

三、接口

(1)什么是接口?

接口是抽象方法和常量值的定义的集合,从本质上讲,接口是一种特殊的抽象类,这种抽象类中包含常量和方法的定义,而没有变量和方法的实现。

(2)接口定义格式

[修饰符] interface 接口名[extends 父接口名列表]

{ 常量数据成员声明

  抽象方法声明

}

(3)接口定义定义规则

Ø 接口中的成员都是public访问类型的。接口里的变量默认是用 public static final标识的 。

Ø 我们可以定义一个新的接口用extends关键字去继承一个已有的接口 。

Ø 我们也可以定义一个类用implements关键字去实现一个接口中的所有方法,我们还可以去定义一个抽象类用implements关键字去实现一个接口中定义的部分方法。 

Ø 一个类可以继承一个父类的同时,实现一个或多个接口,extends关键字必须位于implemnets关键字之前 。

(4)总结:

接口和抽象类的区别???

Java中所有的类有共同的父类java.lang.Object,但接口没有共同的根。接口可以当作抽象类使用。它们的区别如下:

Ø 接口中的每个方法,没有实现部分,都是抽象方法;抽象类中可以有具体的方法。

Ø 接口中的数据必须是常量;抽象类可以有各种类型的数据。

Ø 由于定义在接口中的所有方法都是抽象方法,接口中可以省略abstract修饰符;但是抽象类中的抽象方法必须用abstract修饰。

四、对象的多态性

(1)什么是多态????

用相同的名字定义一系列方法称为多态。

(2)多态性的特点

Ø 子类对象能自动转换成父类。

例:

class A{

public void func1(){

System.out.println("A func1 is calling");

}

public void func2(){

func1();

}

}

class B extends A{

public void func1(){

System.out.println("B func1 is calling");

}

public void func3(){

System.out.println("B func3 is calling");

}

}

class C{

public static void main(String [] args){

B b=new B();

A a = b; //将B类的实例对象b直接赋值给A类的引用类型变量

callA(a);

callA(new B());//创建一个类B的实例对象,传递给需要类A的实例对象做参数的CallA方法,在参数的传递过程中发生了隐式自动类型转换。 

}

public static void callA(A a){

a.func1();

a.func2();

}

}

Ø 如果在编程时,知道CallA方法中传递的形式参数a实际上就是子类B的一个引用对象,想在callA方法中调用子类特有方法,该如何做呢? 

 public static void CallA(A a)

  {

   B b=(B)a;

   b.func1();

   b.func2();

   b.func3();

 }

Ø 强制类型转换的前提是程序员提前就知道要转换成父类引用类型对象的本来面目确实子类类型的。 

(3)instance of 操作符

格式:对象 instanceof 类(或接口)

它的返回值是布尔型的,或真(true)、或假(false)

例:

public static void CallA(A a){

    if(a instanceof B){

      B b=(B)a;

      b.func1();

      b.func2();

      b.func3();

    }

   else{

     a.func1();

     a.func2();

   }

  }

(4)Object类

Object类是Java类层中的最高层类,是所有类的超类。

   public class Person{

    ...

    }

   等价于

   public class Person extends Object

   {

   ...

   }

(5)多态性应用

Ø 应用程序不必为每一个派生类(子类)编写功能调用,只需要对抽象基类进行处理即可。

Ø 派生类的功能可以被基类的引用变量引用,这叫向后兼容,可以提高程序的可扩充性和可维护性。

(6)Overload和Override

Ø 方法的重写(Overriding)和重载(Overloading)是Java多态性的不同表现。

Ø 重写(Overriding)是父类与子类之间多态性的一种表现。(子类中定义的某方法与其父类中的方法有相同的名称和参数)

Ø 重载(Overloading)是一个类中多态性的一种表现(一个类中定义了多个同名的方法,它们有不同的参数个数或有不同的参数类型)。Overloaded的方法是可以改变返回值的类型。

(7)匿名内部类

Ø 有时在定义事件处理代码时,由于代码短小,不必再明确定义一个类,可使用匿名内部类。匿名内部类是final(最终)类,非static类,匿名内部类将类的声明和创建类的实例一步完成。 

Ø 主要应用在事件处理的代码编写中。

例:

class Outer{

public static void main(String [] args){

new Outer().callInner(new A(){

public void fun1()

{

System.out.println("implement for fun1");

}

});

public void callInner(A a)

{

a.fun1();

}

}

五、异常

(1)什么是异常

Ø 异常定义了程序中遇到的非致命的错误, 而不是编译时的语法错误,如程序要打开一个不存的文件、网络连接中断、操作数越界、装载一个不存在的类等,这些事件的发生将阻止程序的正常运行。

Ø 为了加强程序的健壮性,程序设计时,必须考虑到可能发生的异常事件并做出相应的处理。

Ø 在java中,异常本身就是一个对象,产生异常就是产生一个异常对象。这个对象可能有应用程序本身产生,也可能由java虚拟机(jvm)产生,这取决于异常的类型。该异常对象中包括异常事件的类型以及发生异常时应用程序目前的状态和调用过程。

(2)异常的分类

Ø Error:称为错误,由java虚拟机生成并抛出,包括动态连接失败、虚拟机错误等,程序对其不做处理。

Ø Exception:所有异常类的父类,其子类对应了各种各样可能出现的异常事件,一般需要用户显式的声明或捕获。

Ø Runtime Exception:一类特殊的异常,如被0除、数组下标越界等,其产生比较频繁,处理比较麻烦。如果显式的声明或捕获将会对程序可读性和运行效率影响很大,可由系统自动检测并将他们交给缺省的异常处理程序(用户可不必对其处理)。

 

(3)异常的捕获和处理

格式:

try{

     //可能抛出异常的语句

}catch(SomeException1 e1){

  ……

}catch(SomeException2 e2){

  ……

}finally{

   ……

}

Ø Try 语句:

ü Try{…}语句指定了一段代码,该段代码就是一次捕获并处理例外的范围。

ü 在执行过程中,该段代码可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句分别对这些异常做相应的处理。

ü 如果没有例外产生,所有catch代码段都被略过不执行。

Ø Catch语句

ü 在catch语句块中是对异常进行处理的代码,每个try语句可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。

ü 在catch中声明的异常对象(catch(someException e))封装了异常事件发生的信息,在catch语句快中可以使用这个对象的一些方法捕获这些信息。

例:

getMessage()方法,用来得到有关异常事件的信息。

printStackTrace()方法,用来跟踪异常事件发生时执行堆栈的内容。

Ø finally语句

ü 在try...catch语句后,还可以有一个finally语句,finally语句中的代码块不管异常是否被捕获总是要被执行的。

ü 即使try代码块和catch块中使用了return语句退出当前方法或break跳出某个循环,相关的finally代码块都要被执行。

ü finally中代码块不能被执行的惟一情况是:在被保护的代码块中执行了System.exit(0)。

ü 每个try语句必须有一个或多个catch语句对应,try代码块与catch代码块及finally代码块之间不能有其他语句。

 

(4)try…catch语句

Java的异常处理是结构化的,不会因为一个异常影响整个程序的执行。

例:

Test.java类

class Test

{

public int devide(int x, int y)

{

int result = x/y;

return x/y;

}

}

TestException.java类

public class TestException{

public static void main(String [] args){

try{

int reslut = new Test().devide( 3, 0 );

System.out.println("the result is" + reslut );

}

catch(Exception e){

System.out.println(e.getMessage());}

System.out.println("program is running here ,that is normal !");

}}

(5)throws关键字

如果一个方法不想处理异常,可以通过throws 语句将异常抛向上级调用方法。 

例:

TestException.java类

 

public class TestException{

public static void main(String [] args){

try{

int reslut = new Test().devide( 3, 1);

System.out.println("the result is" + reslut );

}

catch(Exception e){

System.out.println(e.getMessage());//或者e.printStackTrace()

}

System.out.println("program is running here ,that is normal !");

}}

Test.java类

class Test 

{

public int devide(int x, int y) throws Exception

{

int result = x/y;

return x/y;

}

}

(6)自定义异常

用户定义的异常类型必须是Throwable的直接或间接子类,java推荐用户定义的异常类型以Exception为直接父类。 

例:

UserException.java类

import java.io.*;

public class UserException{

//抛出异常的方法

void doSomeThing() throws UserDefineException{

int a=0,b=10;//产生异常的条件判断

if(a!=0){

System.out.println("Normal");}

else{//抛出异常

throw new UserDefineException();}}

public static void main(String []args){

UserException one=new UserException();

//调用实例方法

one.doSomeThing();}}

UserDefineException.java类

//用户定义的异常,由Exception类派生

class UserDefineException extends ArithmeticException

{

public UserDefineException()

{

System.out.println("Exception occured");

}

}

MyException.java类

  class MyException extends Exception {

  private int idnumber;

  public MyException(String message, int id) {

super(message);

this.idnumber = id;

 

public int getId() {

return idnumber;

  }

}

(7)使用自定义异常

例:

public class Test12_6{

  public void regist(int num) throws MyException {

  if (num < 0) {

       throw new MyException("人数为负值,不合理",3);

  }

System.out.println("登记人数" + num);

        }

   public void manager() {

  try {

    regist(100);

    } catch (MyException e) {

  System.out.print("登记失败,出错种类"+e.getId()))}

System.out.print("本次登记操作结束"); }

   public static void main(String args[]){

Test12_6 t = new Test12_6();

t.manager();

  }}

(8)异常使用细节

Ø 一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常的子类。

Ø 如果父类抛出多个异常,那么重写(覆盖)方法必须抛出那些异常的一个子集,也就是说,不能抛出新的异常。          

(9)JAVA引用异常的好久

Ø 引入异常处理后,可以使得异常处理代码和程序其他部分分隔开,不仅增加了程序的清晰性、可读性、更重要的是明晰了程序的流程。

Ø 可以对各种不同异常事件进行分类处理,从而具有了良好的接口和层次性。

Ø 利用类的层次性既可以根据不同的异常分别处理,也可以把具有相同父类的多个异常统一处理,从而有相当的灵活性。

Ø 另外,引入异常后,可以从try-catch之间的代码段中快速定位异常出现的位置,提高错误处理的效率。

六、包

(1)什么是包????

package是Java提供的文件(即公共类)的组织方式。一个包对应一个文件夹,一个包中可以包括许多类文件。包中还可以再有子包,称为包等级。 

(2)包的作用

Ø 定位类:具有相似功能的类可以放置在同一个包中,这样可以很容易地查找定位类。

Ø 避免命名冲突:在开发由其他程序员共享的可复用类时,会发生命名冲突,可以把类放在不同包中,通过包名引用类可以避免命名冲突。

Ø 可以方便地分发软件。

Ø 控制类之间的访问(参见第4章访问控制)。

注意:包是一个类名空间,同一个包中的类和接口不能重名,不同包中的类可以重名。 

(3)包的创建

包的创建就是将源程序文件中的接口和类纳入指定的包。一般情况下,Java源程序由四部分组成:

Ø 一个包(package)定义语句(可选项)。其作用是将本源文件中的接口和类纳入指定包。源文件中若有包说明语句,必须是第一个语句;

Ø 若干个(import)语句(可选项)。其作用是引入本源文件中所需要使用的包;

Ø 一个public的类声明。在一个源文件中只能有一个public类;

Ø 若干个属于本包的类声明(可选)。 

包的定义语句格式:package 包名;

例:

package pack1.pack2;

创建包就是在当前文件夹下创建一个子文件夹,存放这个包中包含的所有类和接口的.class文件。package pack1.pack2;语句中的符号“”代表了目录分隔符,说明这个语句创建了两个文件夹。第一个是当前文件夹下的子文件夹pack1;第二个是pack1下的子文件夹pack2 ,当前包中的所有类就存放在这个文件夹里。

(4)包的使用

Ø Java提供了丰富的标准类来帮助程序设计者更方便快捷地编写程序,这些标准类组成了类包,主要有:

java.lang                       java.awt

java.applet                     java.awt.image

java.awt.peer                   java.io

java.net                        java.util

Ø 使用Swing组件进行GUI设计,使用javax.swing包中的类。

Ø 除了java.lang之外,其余类包都不是java语言所必须的。若要使用,必须进行包的导入。

Ø 将类组织成包的目的是为了更好地利用包中的类。通常一个类只能引用与它在同一个包中的类。如果需要使用其它包中的public类,则可以使用如下的几种方法。

Ø 在引入的类前加包名

ü 例如:pack1.pack2.Format.format(23.4533,2); 

Ø 用import关键字加载需要使用的类

ü 例如上面的语句在程序开始处增加了:

ü import  pack1.pack2.Format;语句之后,就可以直接写成:

ü Format.format(23.4533,2);

Ø 用import关键字加载整个包

ü import pack1.pack2.*; 

七、访问控制

(1)访问控制----类成员

Ø private访问控制

     如果一个成员方法或成员变量前使用了private访问控制符,那么这个成员只能在这个类的内部使用。

Ø 默认访问控制

   如果一个成员方法或成员变量名前没有使用任何访问控制符,我们就称这个成员是默认的(default),或是友元的(friendly),或是包类型的(package)。对于默认访问控制成员可以被这个包中的其他类访问,如果一个子类与父类位于不同的包中,子类也不能访问父类中的默认访问控制成员。

Ø protect访问控制

   如果一个成员方法或成员变量名前使用了protected访问控制符,那么这个成员即可以被同一个包中其他类访问,也可以被不同包中的子类访问。

Ø public访问控制

     如果一个成员方法或成员变量明前使用了public访问控制符,那么这个成员即可以被所有类访问,不管访问类与被访问类是否在同一个包中。

(2)访问控制----类

类本身也有访问控制,即在定义类的class关键字前加上访问控制符,但类本身只有两种访问控制,即public 和默认,父类不能是private 和protected,否则子类无法继承。public修饰的类能被所有的类访问,默认修饰(即class关键字前没有访问控制符)的类,只能被同一包中的所有类访问。

八、JAVA的命名规范

下面是java中的一些命名习惯,假设xxx,yyy,zzz分别是一个英文单词的拼写。 

Ø 包名中的字母一律小写,如:xxxyyyzzz。

Ø 类名、接口名应当使用名词,每个单词的首字母大写,如:XxxYyyZzz。

Ø 方法名,第一个单词小写,后面每个单词的首字母大写,如:xxxYyyZzz。

Ø 变量名,第一个单词小写,后面每个单词的首字母大写,如:xxxYyyZzz。

Ø 常量名中的每个字母一律大写,如:XXXYYYZZZ

 

 

 

 

 

 

 

 

你可能感兴趣的:(java,corejava)