黑马程序员——面向对象

来源:互联网 发布:手机淘宝我的店铺 编辑:程序博客网 时间:2024/06/06 16:34

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

面向对象

三个特征:封装 继承 多态

找对象、建立对象、使用对象、维护对象的关系。

面向对象和面向过程的区别:

(1)面向过程强调功能

(2)面向对象强调具有功能的对象

面向对象和面向过程都是一种编程思想,面向对象是基于面向过程的,即万物皆对象

面向对象的特点:

1. 是一种符合人们思考习惯的思想

2. 可以将复杂的事情简单化

3.将程序员从执行者转换成了指挥者

4. 完成需求时:

              1.先要去找具有所需的功能的对象来用。

              2.如果该对象不存在,那么创建一个具有所需功能的对象。

              3.这样简化开发并提高复用。

开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。

设计的过程:其实就是在管理和维护对象之间的关系。

类和对象的关系:

类  :对现实生活中事物的描述

对象:一类事物,实实在在存在的个体,实体

类的定义:   

描述事物其实是在描述事物的属性和行为。

在Java中用class来描述事物:

属性对应是类中变量

行为对应类中的函数(方法)。

定义类其实是在定义类中的成员(成员变量和成员函数)

成员变量和局部变量的区别:

作用范围:

         成员变量定义在类中,作用于整个类中。

         局部变量定义在局部范围内,作用于函数中或语句中

在内存中的位置:

         成员变量在堆内存中,随着对象的建立而建立,成员变量有默认初始化值

         局部变量存储在栈内存中,作用范围结束变量空间就会自动释放,没有默认初始化值 

创建对象

在Java中通过new关键字来建立对象,即在堆内存中产生一个实体

         eg:Car c=new Car();

c就是一个类类型变量,类类型变量指向对象。

在Java中通过对象.对象成员来指挥对象

匿名对象使用方法

方法1:当对对象的方法只调用一次时,可以用匿名对象来完成

         eg:newCar().run();

方法2:可以将匿名对象作为实际参数进行传递

 

封装

定义:隐藏对象的属性和细节,仅对外提供公共访问方式

好处:

将变化隔离

便于使用

提高重用性

提高安全性

封装原则:

将不需要对外提供的内容都隐藏起来

把属性都隐藏,提供公共方法对其访问

private

私有的(权限修饰符),用于修饰类中的成员(成员变量 成员函数)

              私有的只在本类中有效,当类中某个成员变量/函数被私有了,类以外即使建立了对象也不能直接访问该成员(变量)。

              私有仅仅是封装的一种表现形式

              对外提供公共访问方式,就可以在访问方式中加入逻辑判断等语句。

              对访问的数据进行操作,提高代码的健壮性。


构造函数

特点:

1、函数名与类名相同

2、不用定义返回值类型

3、不用写return语句

作用:

给对象进行初始化

     多个构造函数使用重载的形式存在的

     对象一建立就会调用与之对应的构造函数

     当一个类中没有定义构造函数时,系统会默认给该类加入一个空参数的构造函数

     当类中自定义了构造函数后,默认的构造函数就没有了。

构造函数和一般函数的区别:

1:定义写法上不同

 2:运行上不同

构造函数是对象一建立就运行,给对象初始化

一般方法是对象调用才执行,是给对象添加对象具备的功能

3:运行次数上不同

构造函数:一个对象建立,构造函数只运行一次

一般方法:可以被该对象调用多次

什么时候定义构造函数?

当分析事物时,该事物存在就具备一些特性或行为,就将这些内容定义在构造函数中

 

构造代码块 {}

作用:给对象进行初始化。对象一建立就运行,而且优先于构造函数执行

和构造函数的区别:

构造代码块是给所有的对象进行统一的初始化

而构造函数是给对应的对象初始化

构造代码块中定义的是不同对象共性的初始化内容

 

this关键字

this:代表它所在函数所属对象的引用

即哪个对象在调用this所属的函数,那么this就代表哪个对象、

this的应用:

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

但凡本类功能定义使用到了本类对象,都用this表示

this语句:用于构造函数之间进行互相调用

this语句只能定义在构造函数的第一行,因为初始化要先执行

 

静态:static

用法:是一个修饰符,用于修饰成员(成员变量,成员函数),当一个成员被静态修饰时,除了可以被对象调用外,还可以直接被类调用

调用方式    类名.成员变量

static特点:

1、随着类的加载而加载,随着类的消失而消失,它的生命周期长

2、优先于对象存在,静态是先存在的,对象时后存在的

3、被所有对象所共享

4、可以直接被类所调用

静态使用注意事项:

1:静态方法只能访问静态成员(变量和方法)

非静态方法既可以访问静态也可以访问非静态

2:静态方法中不可以定义this,super关键字

  因为静态优先于对象存在,所以静态方法不能出现this

3:主函数是静态的

静态的利与弊:

利:对对象的共享数据进行单独空间的存储,节省空间。可以直接被类名调用

弊:生命周期长,访问出现局限性。(静态虽好,只能访问静态)

如何使用静态成员变量和函数

静态变量:当对象中出现共享数据时

静态函数:当功能内部没有访问到非静态数据(对象的特有数据)就可以定义成静态的

静态的应用

建立ArrayTool工具类 然后在ArrayToolDemo类中调用

int[]arr={3,5,6,43,7,4};

ArrayTool tool=newArrayTool();

intmax=tool.getMax(arr);

在上述通过建立ArrayTool的对象使用这些工具方法对数组进行操作是发现了问题:

1、对象是用于封装数据的,可是ArrayTool对象中并未封装特有数据。

2、操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。

因此,为了让程序更加严谨,可以不需要对象。 可以将ArrayTool中的方法都定义成static的,直接通过类名调用。

eg:   public static int getMax(int[] arr)

将方法都静态后,可以方便于使用,但该类还是可以被其他程序建立对象,为了使程序更加严谨,强制让该类不能建立对象,可以通过将构造函数私有化

eg:   private ArrayTool(){}

实例变量和类变量的区别:

1、存放位置

类变量随着类的加载而存在于方法区中

实例变量随着对象的建立而存在于堆内存中

2、生命周期

类变量生命周期长,随着类的消失而消失

实例变量生命周期随着对象的消失而消失

 

主函数

是一个特殊的函数。作为程序的入口,可以被jvm调用。

public static void main(String[] args)

主函数的定义的分解

public:代表该函数的访问权限最大

static:代表主函数随着类的加载就已经存在了

void  :主函数没有具体的返回值

main  :不是关键字,但是是一个特殊的单词,可以被jvm识别

(String[] args):函数的参数,参数类型是一个数组,该数组中的元素是字符串。字符串类型的数组,其中args表示arguments(参数) args是一个数组变量,可以改变

主函数是固定格式的可以被jvm识别

 

代码块的分类

局部代码块:对局部变量的生命周期进行控制

构造代码块:对所有对象进行初始化

静态代码块:对类进行初始化

静态代码块

格式:

static{

静态代码块中的执行语句;

}

特点:随着类的加载而执行,只执行一次,并优先于主函数。用于给类进行初始化


继承

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么这些类无需再定义这些属性和行为,只要继承单独的那个类即可。

多个类可以称为子类,单独这个类称为父类或者超 类。

子类可以直接访问父类中的非私有的属性和行为。

通过extends关键字让类与类之间产生继承关系。

class SubDemo extends Demo{}

继承特点

              1.提高代码的复用性。

              2.让类与类之间产生关系,有了这个关系才有了多态的特性

     注意:千万不要为了获取其他类的功能或者简化代码而继承

            必须是类与类之间有所属关系才可以继承。

Java语言中只支持单继承,不支持多继承

 多继承容易带来安全隐患即当多个父类中定义了相同功能但他们功能的内容不同时,子类对象不确定要使用哪一个功能,

但Java保留这种机制,并且使用另外一种体现形式来完成即多实现。

Java支持多层继承,也就是一个继承体系

使用继承体系中的功能:查阅父类功能,创建子类对象使用该功能 

子父类出现后,类成员(变量 函数 构造函数)的特点

1、变量:

如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this;

子类要访问父类中的同名变量,用super

super的使用和this几乎一致

this代表的是本类对象的引用

super代表的是父类对象的引用

2、子父类中的函数

当子类出现和父类一模一样的函数时,子类对象调用该函数,会运行子类函数的内容,如同父类的函数被覆盖一样。这种情况是函数的特性:重写(覆盖)。当子类继承父类,沿袭父类的功能到子类中,虽然子类具备该功能,但是功能内容却与父类不一样,这时候没必要定义新功能,而是使用函数的覆盖特性,保留父类的功能定义,并重写功能内容

3、子父类中的构造函数

在对子类对象进行初始化时,父类的构造函数也会运行,因为子类的构造函数默认第一行有一条隐式的super()语句,super()会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super()

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

因为父类中的数据,子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造函数。如果要访问父类中指定的构造函数,通过super(参数)的方式来指定

注意:super语句一定定义在子类构造函数的第一行

覆盖特点:

              1、子类覆盖父类,必须保证子类权限大于等于父类,否则编译失败

              2、静态只能覆盖静态

重载与重写的区别:

              重载:只看同名函数的参数列表

              重写:子父类方法一模一样


子类的实例化过程

子类的所有构造函数默认都会访问父类中空参数的构造函数,因为子类每一个构造函数的第一行都有一句隐式super();

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

当然子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数

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


final:最终(修饰符)

特点:

1、可以修饰类,函数,变量

2、被final修饰的类不可以被继承。避免继承时被子类复写功能。(弥补了继承打破封装性的弊端)

3、被final修饰的方法不可以被复写

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

       常量书写:所有字母都大写,若由多个单词组成,单词之间用_连接。

5、类部类定义在类中的局部位置上,只能访问该局部被final修饰的局部变量。

抽象类

定义:

当多个类中出现相同功能,但功能主体不同,这时可以进行向上抽取,但只抽取功能定义,不抽取功能主体。

格式:

     abstract  class  类名{

         abstract  返回值类型  函数名(参数列表);

     }

特点:

1、抽象方法一定在抽象类中

2、抽象方法和抽象类都必须用abstract关键字修饰

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

4、抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用,如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类      

抽象类与一般类的区别:

抽象类比一般类多了抽象方法,就是在类中可以定义抽象方法。

抽象类不可以实例化。

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

接口

初期理解可以认为是一个特殊的抽象类

当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示

接口格式

     interface 接口名{  }

接口定义时格式:

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

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

         常量:publicstatic final

         方法:publicabstract

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

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

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

接口的特点:

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

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

3、接口可以多实现;

4、类与类之间是继承关系,类与接口直接是实现关系,类可以在继承一个类的同时实现多个接口

5、接口之间是继承关系(java支持多继承,只有在接口中体现,类中是通过接口的实现);

              子类先继承在多实现   class Xx extends Yy implements Cc,Dd

抽象类和接口的异同点:

相同点:

都是不断向上抽取而来的。 

不同点:

1.抽象类需要被继承,而且只能单继承。

 接口需要被实现,而且可以多实现。

2.抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。

 接口中只能定义抽象方法,必须由子类去实现。

3.抽象类的继承,是is a关系,在定义该体系的基本共性内容。

 接口的实现是 like a 关系,在定义体系额外功能。

     接口举例:

 interface Inter{

              public staticfinal int NUM=3;

              public abstractvoid show();

}

class Test implements Inter

{

              public voidshow(){}

class Demo{

              public static voidmain(String[] args){

                  Test t=newTest();

                  System.out.println(t.NUM);//对象调用成员

                  intln(Test.NUM);//类调用成员

                  System.out.println(Inter.NUM);//接口名调用接口中成员

                  //不能对接口中NUM赋值

              }

}

多态

定义:某一类事物的多种存在形态

1、多态的体现

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

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

2、多态的前提

必须保证类与类之间存在关系,要么继承,要么实现

存在覆盖

3、多态的利与弊

利:大大提高了程序的扩展性

前期的代码可以使用后期的内容

弊:只能使用父类的引用访问父类的成员

4、多态的应用

Animal a=new Cat();//类型提升,向上转型

a.eat();//猫对象提升成为动物类型,无法访问猫特有的功能

Cat c=(Cat)a;//要调用猫特有功能,强制将父类的引用转成子类类型  向下转型

c.catchMouse();

Animal a=new Animal();//错误操作:将父类对象转成子类类型

Cat c=(Cat)a;

能转型的是父类的引用指向了自己的子类对象,该引用可以被提升,也可以被强制转型。

多态自始至终都是子类对象在做着变化

 

在多态中成员的特点

1、成员函数(非静态):

编译时:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过;没有的编译失败。

运行时:参阅对象所属的类中是否有调用方法。

即:编译看左边,运行看右边.(成员函数存在覆盖特性)

2、成员变量

无论编译和运行,都参考左边(引用型变量所属的类).

3、静态函数

无论编译和运行,都参考左边

原因:当类一被加载,静态函数就随类绑定在了内存中。此时,不需要创建对象,就可以使用类名直接调用。父类中的静态成员函数一般是不被复写的。

Object特点:

所有对象直接或者间接的父类,即传说中的上帝

该类中定义的是所有对象都具备的功能。

Object中已经提供了equals(Objectobj)方法来比较两对象是否相同,如果自定义类中也有比较相同的功能,那么没必要重新定义,只要沿袭父类中的功能,建立自己特有比较内容即可,这就是覆盖。

 

内部类

定义:

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

访问规则:

1、内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有一个外部类的引用,即外部类名.this

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

访问格式:

1、内部类定义在外部类成员位置

1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象。

式:    Outer.Inner in=newOuter().new Inner();

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

private:将内部类在外部类中封装。

static:内部类就具备静态特性。

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

在外部其他类中直接访问static内部类中的非静态成员

              static class Inner

              {

                   void function(){}

              }

              new Outer.Inner().function();

在外部其他类中直接访问static内部类中的静态成员

              static class Inner

              {

                   static void function(){}

              }

              Outer.Inner.function();

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

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

2、内部类定义在外部类局部

内部类定义在外部类中的某个方法中,创建了这个类型的对象时,且仅使用了一次,那么可在这个方法中定义局部类。

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

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

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

class Outer

{

     private int x=3;

     class Inner//内部类

     {

         int x=4;

         void function()

         {

              int x=6;

              System.out.println("inner:"+x);//x=6

              System.out.println("inner:"+this.x);//x=4

              System.out.println("inner:"+Outer.this.x);//x=3

         }

     }

     void method()

     {

         Inner in=new Inner();//建立内部类对象访问内部类

         in.function();

     }

}

 方法中的内部类不能访问方法中的局部变量

他们的生命周期不一样,内部类是也是一个类,是存储在堆中,也只有当对该类的引用消失时,内部类才会消亡。而方法的局部变量是存储在堆栈中的,当调用结束时就会退栈,即在内存中这个属性就消失了。也就是说,内部类的生命周期超过了方法中局部变量的生命周期,内部类可能会调用到已经消失的属性,因此内部类不能访问方法中的局部变量。解决方法就是在局部变量前加修饰符final

匿名内部类

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

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

3、匿名内部类的格式:

                   new 父类或者接口()

                   {

                       定义子类的内容;

                   }

4、其实匿名内部类就是一个匿名子类对象。

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

abstract class AbsDemo

{

     abstract void show();

}

 

class Outer

{

     int x=3;

     public void function()

     {

         new AbsDemo()

         {

              void show()

              {

                   System.out.println("show:"+x);

              }

         }.show();//等价于 newInner().show();

         //AbsDemo的匿名子对象调用show方法   即匿名内部类调用方法

     }

}

//在外部其他函数中访问

new Outer.function();

如果没有写父类或者接口类,能够用匿名内部类吗? 可以,父类可以是Object;


创建对象时子父类中构造代码块 构造函数调用顺序:

class FuLei{static{System.out.println("父类静态代码块");}FuLei(){System.out.println("父类构造函数");}{System.out.println("父类构造代码块");}public void function(){System.out.println("父类一般方法");}}class ZiLei extends FuLei{static{System.out.println("子类静态代码块");}ZiLei(){System.out.println("子类构造函数");}{System.out.println("子类构造代码块");}public void function(){System.out.println("子类一般方法");}}public class DaiMaKuaiTest {public static void main(String[] args) {FuLei zi=new ZiLei();zi.function();}}
父类静态代码块
子类静态代码块
父类构造代码块
父类构造函数
子类构造代码块
子类构造函数
子类一般方法


 

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

0 0
原创粉丝点击