JavaSE_面向对象4

来源:互联网 发布:淘宝发货地可以改吗 编辑:程序博客网 时间:2024/06/05 15:59

1、课程名称:面向对象(高级)

2、知识点

2.1、上次课程的主要知识点

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

         · 封装:封装可以封装类中的任意的操作,包括属性、方法、构造方法,但是封装之后类中的内容对外部不可见,不可见在进行一些简单操作的时候将非常的麻烦,所以后来使用了内部类来解决的这样问题,但是内部类本身会破坏程序的结构。所以在此基础之上为了可以方便的扩充类的功能,加入了继承。

         · 继承:继承就是扩展已有类的功能的,但是一般的继承并不是继承一个普通的类,而是继承抽象类或实现接口,但是抽象类和接口本身不能直接实例化,所以需要依靠多态性,以通过子类实例化。

         · 多态:一个同样的功能操作,可以根据其所在位置的不同,完成的具体操作也不同,包括方法的重载、方法的覆写、以及最重要的对象的多态性,父类或父接口根据实例化其子类的不同,完成的具体操作也不同。但是操作的标准都是一样的。

2、   抽象类和接口的概念及实例化操作

         · 抽象类本身具备的是一种模板设计,可以按照固定的操作完成相关的代码。

         · 接口本身以一种标准的形式出现。

3、   对象多态性:子类和父类实例进行相互转型

         · 向上转型,自动完成的,使用父类接收子类的实例,此种用法使用的最多

         · 向下转型,强制完成,但是在进行向下转型之前首先一定要发生向上转型,以建立关系,但是一般使用较少

4、   设计标准:一个子类永远不要去继承一个已经实现好的类,要么继承抽象类,要么实现接口。

5、   Object类:是所有类的父类,可以接收所有对象的引用。

         · Object类中存在toString()和equals()方法用于对象的输出和比较

         · Object类可以接收任意的引用数据类型的实例

2.2、本次预计讲解的知识点

1、   抽象类和接口

2、   匿名内部类

3、   包装类及JDK 1.5的新特性

3、具体内容

3.1、抽象类和接口(重点

         抽象类和接口在Java中是最重要的两个概念,那么这两个概念有很多实际的应用,和操作,下面通过一些代码来进行分析。

3.1.1、抽象类和接口的关系

         之前学习过了内部类,内部类:在一个类的内部还包含另外一个类,那么在一个抽象类中也是允许包含其他的抽象类或其他的接口的。

abstract class A { // 定义了抽象类

         public abstract void fun() ;     // 抽象方法

         abstract class B{         //定义了内部抽象类

                   public abstract void print() ;

         };

         interface C{        //定义了内部的接口

                   public void getInfo() ;        

         }

};

         在以上的抽象类中包含了一个抽象类和一个接口,当然,在实际中还可以定义更多的抽象类和接口,那么该怎么使用呢?

         首先对于抽象类A而言应该被子类所继承。

 

abstract class A { // 定义了抽象类

         public abstract void fun() ;     // 抽象方法

         abstract class B{  // 定义了内部抽象类

                   public abstract void print() ;

         };

         interface C{         // 定义了内部的接口

                   public void getInfo() ;  

         }

};

class X extends A{       // 继承抽象类A

         public void fun(){

                   System.out.println("HELLO VINCE") ;

         }       // 子类可以不去实现内部的抽象类和接口

         class Y extends B{       // 定义内部类实现抽象类中的内部抽象类

                   public void print(){

                            System.out.println("HELLO MJW") ;

                   }

         };

         class Z implements C{

                   public void getInfo(){

                            fun() ;

                            new Y().print() ;

                   }

         };

};

public class AIDemo01{

         public static void main(String args[]){

                   A.C c = new X().new Z() ;

                   c.getInfo() ;

         }

};

         以上的操作代码看起来就一个字“晕”,此种代码二十年都见不到。所以只是作为一个简单的参考。

         反过来,一个接口中也能包含多个抽象类或多个接口。

interface A {        // 定义了抽象类

         public void fun() ;         // 抽象方法

         abstract class B{  // 定义了内部抽象类

                   public abstract void print() ;

         };

         interface C{         // 定义了内部的接口

                   public void getInfo() ;  

         }

};

class X implements A{ // 继承抽象类A

         public void fun(){

                   System.out.println("HELLO VINCE") ;

         }       // 子类可以不去实现内部的抽象类和接口

         class Y extends B{       // 定义内部类实现抽象类中的内部抽象类

                   public void print(){

                            System.out.println("HELLO MJW") ;

                   }

         };

         class Z implements C{

                   public void getInfo(){

                            fun() ;

                            new Y().print() ;

                   }

         };

};

public class AIDemo02{

         public static void main(String args[]){

                   A.C c = new X().new Z() ;

                   c.getInfo() ;

         }

};

         实际上,从以上的程序中可以很好的证明一点,类或接口都永远可以作为内部接口或类的情况出现。

3.1.2、接口应用(一):表示工厂设计模式(简单工厂,

抽象工厂,工厂方法)

工厂模式:为创建对象提供了接口

现在,观察以下的程序代码,分析操作的问题:

interface Fruit{    // 定义水果

         public void eat() ;          // 吃水果

}

class Apple implements Fruit{        // 定义苹果的子类

         public void eat(){

                   System.out.println("** 吃苹果。") ;

         }

};

class Orange implements Fruit{

         public void eat(){

                   System.out.println("** 吃橘子。") ;

         }

};

public class AIDemo03{

         public static void main(String args[]){

                   Fruit f = new Apple() ;

                   f.eat() ;

         }};

         以上的代码已经完成了基本的功能,但是以上的操作是否存在问题呢?

         本道程序的问题在于:客户端(main方法)直接与具体的子类相耦合了,如果以后要想更换操作的子类,则必须修改客户端。那么这样的操作在开发中是极其不提倡的一种操作。

         开发的原则:如果可以由A直接到B,那么中间最好加上一个过渡的C,A à C à B。

         为了解决以上的问题,中间一个过渡的操作类,通过此过渡的操作类得到接口的实例化对象。

interface Fruit{    // 定义水果

         public void eat() ;          // 吃水果

}

class Apple implements Fruit{        // 定义苹果的子类

         public void eat(){

                   System.out.println("** 吃苹果。") ;

         }

};

class Orange implements Fruit{

         public void eat(){

                   System.out.println("** 吃橘子。") ;

         }

};

class Factory{

         public static Fruit getInstance(String className){

                   if("apple".equals(className)){

                            return new Apple() ;

                   }

                   if("orange".equals(className)){

                            return new Orange() ;

                   }

                   return null ;

         }

};

public class AIDemo04{

         public static void main(String args[]){

                   Fruit f = Factory.getInstance(args[0]) ;

                   if(f!=null){

                            f.eat() ;

                   }

         }

};

         如果以后程序中再增加子类,直接修改Factory类即可,所以这样的设计在设计模式上讲称为工厂设计模式。

3.1.3、接口应用(二):代理设计模式

         使用接口还可以表示出以下的一种关系。

interface Subject{         // 定义一个操作的主题

         public void giveMoney() ;     // 给我钱。。。。。

}

class RealSubject implements Subject{

         public void giveMoney(){

                   System.out.println("还钱,就两个字。。。") ;

         }

};

class ProxySubject implements Subject{

         private Subject sub = null ;

         public ProxySubject(Subject sub){

                   this.sub = sub ;

         }

         public void before(){

                   System.out.println("准备刀子,绳索,毒药,电辊,锯。") ;

         }

         public void giveMoney(){

                   this.before() ;

                   this.sub.giveMoney() ; // 代表真实的讨债人员去要银子

                   this.after() ;

         }

         public void after(){

                   System.out.println("销毁一切的罪证,我清白的。。。") ;

         }

};

public class AIDemo05{

         public static void main(String args[]){

                   Subject real = new RealSubject() ;

                   Subject proxy = new ProxySubject(real) ;

                   proxy.giveMoney() ;

         }

};

         最终结果,真实主题的操作被调用,只是代理要完成一些与具体业务相关的操作。

3.1.4、接口应用(三):适配器(了解)

        

 

适配器还可以进行进一步的扩充,例如,现在有以下一种情况:

         · 正常情况下一个接口中的所有方法在子类中都必须实现,但是现在要求一个子类可以根据自己的需要来选择实现那种方法,该如何操作呢?

interface Demo{

         public void funA() ;

         public void funB() ;

         public void funC() ;

         public void funD() ;

         public void funE() ;

}

abstract class DemoAdapter implements Demo{

         public void funA(){}

         public void funB(){}

         public void funC(){}

         public void funD(){}

         public void funE(){}

};

class RealDemo extends DemoAdapter{

         public void funA(){

                   System.out.println("Hello World!!!") ;

         }

};

public class AIDemo07{

         public static void main(String args[]){

                   Demo d = new RealDemo() ;

                   d.funA() ;

         }

};

         以上也是适配器的一种设计思路,但是这种设计思路只有在Java的图形界面开发中才会使用,在Java EE的开发中很少应用。

3.1.5、抽象类和接口的区别(记下)

         抽象类与接口在使用上形式如此相似,那么到底两者有那些区别呢,下面通过以下的表格进行罗列,以下的表格要求必须掌握。

No.

区别点

抽象类

接口

1

定义

包含一个抽象方法的类

抽象方法和全局常量的集合

2

语法

通过abstract关键字定义

通过interface关键字定义

3

使用

抽象类通过extends本子类继承

通过implements被子类实现

4

限制

一个子类只能继承一个抽象类

一个子类可以同时实现多个接口

5

关系

一个抽象类可以实现多个接口

一个接口不能继承抽象类,只能继承接口

一个抽象类可以包含多个接口

一个接口中可以包含多个抽象类

6

设计模式

模板设计

工厂设计、代理设计

两者一起使用,可以建立适配置器设计模式

7

开发

存在单继承局限

无此限制

         从以上的表中,可以得出以下的一个结论,如果在开发中接口和抽象类都可以同时出现的话,那么接口的使用优先。

3.1.6、观察以下程序的执行结果

abstract class A{

         public A(){

                   this.print() ;

         }

         public abstract void print() ;

};

class B extends A{

         private int temp = 30 ;

         public B(int temp){

                   this.temp = temp ;

         }

         public void print(){

                   System.out.print("temp = " + this.temp) ;

         }

};

public class AIDemo08{

         public static void main(String args[]){

                   new B(100) ;

         }

};

         以上程序的返回值是0,为什么是0呢?

         构造方法:为类中的属性初始化,如果一个类中的构造方法还没有调用,则类中的所有属性的内容都是默认值。

3.2、匿名内部类(重点

         匿名内部类本身是一个在日后的开发中最经常使用到的一种操作,匿名内部类本身是在抽象类和接口的基础之上发展起来的一种产物。

interface A{

         public abstract void print() ;

};

 

class B implements A{

         public void print(){

                   System.out.println("hello world!!!") ;

         }

};

class X{

         public void fun1(){

                   this.fun2(new B()) ;

         }

         private void fun2(A a){

                   a.print() ;

         }

};

public class AIDemo06{

         public static void main(String args[]){

                   new X().fun1() ;

         }

};

         但是,如果现在B类只使用一次的话,那么还有必要将其定义成一个具体的类吗?

         所以现在如果将接口的子类单独定义成一个类,就有些多余了,那么此时就可以利用匿名内部类完成操作。

interface A{

         public abstract void print() ;

};

class X{

         public void fun1(){

                   this.fun2(new A(){

                            public void print(){

                                     System.out.println("Hello World!!!") ;

                            }

                   }) ;

         }

         private void fun2(A a){

                   a.print() ;

         }

};

public class AIDemo10 {

         public static void main(String args[]){

                   new X().fun1() ;

         }

};

         以上的操作语法虽然别扭,但是必须使用,必须熟练掌握,为日后的开发打下基础。

3.3、包装类(重点

         在Java中有一个设计的原则“一切皆对象”,那么这样一来Java中的一些基本的数据类型,就完全不符合于这种设计思想,因为Java中的八种基本数据类型并不是引用数据类型,所以Java中为了解决这样的问题,引入了八种基本数据类型的包装类。

No.

基本数据类型

包装类

1

int

Integer

2

char

Character

3

float

Float

4

double

Double

5

boolean

Boolean

6

byte

Byte

7

short

Short

8

long

Long

         以上的八种包装类,可以将基本数据类型按照类的形式进行操作。

         但是,以上的八种包装类也是分为两种大的类型的:

                  ·Number:Integer、Short、Long、Double、Float、Byte都是Number的子类表示是一个数字。

                   ·Object:Character、Boolean都是Object的直接子类。

         以下以Integer和Float为例进行操作

3.3.1、装箱及拆箱操作

         将一个基本数据类型变为包装类,那么这样的操作称为装箱操作。将一个包装类变为一个基本数据类型,这样的操作称为拆箱操作,因为所有的数值型的包装类都是Number的子类,Number的类中定义了如下的操作方法,以下的全部方法都是进行拆箱的操作。

No.

方法

类型

描述

1

public byte byteValue()

普通

将包装类的类型变为byte类型,Byte à byte

2

public abstract double doubleValue()

普通

Double à double

3

public abstract float floatValue()

普通

Float à float

4

public abstract int intValue()

普通

Integer à int

5

public abstract long longValue()

普通

Long à long

6

public short shortValue()

普通

Short à short

         如果要想装箱,直接使用各个包装类的构造方法即可。

         · Integer的构造方法:public Integer(int value)

         · Float的构造方法:public Float(float value)

范例:观察装箱及拆箱操作

public class WrapDemo01{

         public static void main(String args[]){

                   int temp = 10 ;     // 基本数据类型

                   Integer x = new Integer(temp) ;       // 将基本数据类型变为包装类,属于装箱操作

                   int y = x.intValue() ;     // 将包装类变为基本数据类型,属于拆箱操作

                   System.out.println(y * y) ;

         }

};

         以上的操作完成之后,下面再以Float为例完成。

范例:观察Float的操作

public class WrapDemo02{

         public static void main(String args[]){

                   float temp = 10.3f ;       // 基本数据类型

                   Float f = new Float(temp) ;    // 将基本数据类型变为包装类,属于装箱操作

                   float y = f.floatValue() ;         // 将包装类变为基本数据类型,属于拆箱操作

                   System.out.println(y * y) ;

         }

};

         以上两个操作完成了基本的装箱及拆箱的操作,但是以上的做法是属于JDK 1.4之前的做法。

         · 在JDK 1.4之前,所有的基本数据类型必须进行手工的装箱及拆箱操作,而且包装类本身不能直接进行四则运算,或者自增、自减的操作。

         · 在JDK 1.5之后,Java中增加了新的功能,可以自动装箱和拆箱。而且可以直接通过包装类进行四则运算和自增加、自减的操作。

范例:以Float为例,观察自动的装箱和拆箱操作

public class WrapDemo03{

         public static void main(String args[]){

                   Float f = 10.3f ;   // 自动装箱

                   float x = f ;          // 自动拆箱

                   System.out.println(f * f) ;                // 直接利用包装类完成

                   System.out.println(x * x) ;              // 直接利用包装类完成

         }

};

         此操作的特点改进从.net平台中学来。这一点为程序的开发带来了极大的好处。

3.3.2、转型操作

         在包装类中最大的好处还在于,可以将一个字符串变为指定的基本数据类型,此点在一般的输入数据上使用较多。

在Integer类中提供了以下的操作方法:

         · 将String变为int型数据:publicstatic int parseInt(String s) throws NumberFormatException

在Float类中提供了以下的操作方法:

         · 将String变为float型数据:publicstatic float parseFloat(String s) throws NumberFormatException

但是,在执行以上操作的时候要求有一点,字符串必须由数字组成,否则会出现错误。

public class WrapDemo04{

         public static void main(String args[]){

                   String str = "123" ;       // 定义字符串由数字组成

                   int x = Integer.parseInt(str) ;  // 将字符串变为int型数据

                   System.out.println(x * x) ;

         }

};

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

public class WrapDemo03{

         public static void main(String args[]){

                   String str = "123.5" ;    // 定义字符串由数字和一个小数点组成

                   float x = Float.parseFloat(str) ;        // 将字符串变为float型数据

                   System.out.println(x * x) ;

         }

};

4、访问修饰符、包(补充)

访问修饰符:public、private、protected、defult

包:分类管理java文件、命名空间

5、总结

1、   抽象类和接口的实际应用及区别

2、   匿名内部类是使用一次的类,在日后的开发中作用较大

3、   包装类可以将基本数据类型以引用类的形式进行操作,在JDK 1.5之后提供了自动装箱及拆箱的操作,使用包装类可以将一个字符串方便的变为基本数据类型。


原创粉丝点击