黑马程序员-面向对象1

来源:互联网 发布:ant 调用python 编辑:程序博客网 时间:2024/05/22 11:43

——-android培训java培训期待与您交流!———-

1.面向对象概念


a.面向对象概念

  • 理解面向对象:面向对象是面向过程而言。是一种思想。将功能封装进对象,强调具备了功能的对象。
  • 任何事物都能抽象成对象,比如人。人都有共性:年龄,性别,身高,学历等等。把人抽象成对象,而这个人对象内部的功能可以定义成年龄,性别,身高等等这些;而对于外界想要调用你这个人的某个功能属性,对他来说不必关心你人对象内部的实现,他只管调用你的这个对象某个功能,获取他需要的结果即可。方便快捷,提高编程效率。
  • 面向对象三个特征:封装、继承、多态

b.类与对象的关系

  • 类:对现实生活中事物的描述。
  • 对象:就是实实在在的个体的这类事物。
  • 定义:
    A. 定义类就是在描述事物,也就是在定义属性和行为。属性和行为共同成为类中的成员(成员变量,成员函数)。
    B. 对象由new操作符来生成,在堆内存产生一个实体。
  • 示例:
//定义类    class People{    //属性    public int age;    public string name;    ...    //定义方法 行为    public int age()    {            return age;    }
    //对象    People p = new People();    p.age();    ...
  • 成员变量和局部变量
    A.最大区别区别:作用的范围不一样。成员变量作用于整个类中,从属于类,不必初始化。局部变量作用于函数中或者语句中,必须手动初始化。
    B.内存的位置:成员变量在堆内存中,因为对象的存在才存在于内存中。局部变量存在栈内存中。
  • 匿名对象
    A.匿名对象是对象的简化形式,没有名字的对象。格式为new 实例名称();
    B.匿名对象两种使用情况:
    (1).当对对象方法仅进行一次调用时
    (2).匿名对象可以作为实际参数进行传递
new People().age = 23;
age(new People());

c.封装

  • OOP三大特征之一。
  • 概念:指隐藏独享的属性和实现细节,仅对外提供公共访问方式。
  • 封装的好处:将变化隔离、便于使用、提高重用性、提高安全性
  • 封装原则:将不需要对外提供的内容都隐藏起来、把属性都隐藏,提供公共方法对其访问。
  • private:私有权限反问修饰符。用于修饰类中的成员(成员变量,成员函数),私有指只在本类中有效。仅仅是封装的一种表现形式。

d.构造函数

  • 特点:函数名与类名相同、不用定义返回值类型、不可以写return语句。
  • 作用:给对象初始化,用于对象初始化。
  • 注意:当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数,用于对象初始化。当在类中定义了初始化构造函数,默认的构造函数就没有了。
  • 构造函数和一般函数在写法上不同在运行上也不同,构造函数是在对象一建立就运行,给对象初始化。而一般方法是对象调用才执行,给是对象添加对象具备的功能一个对象建立,构造函数值运行一次,而一般方法可以被该对象调用多次。
//定义类class People{    //默认构造函数    People(){}}
  • 定义构造函数的时间:当对象需要一定的特征或者行为,就需要对其进行构造函数。

构造代码块

//定义类class People{    /**     * 作用:给对象进行初始化     * 特点:对象一建立就运行,而且优先于构造函数执行,针对所有的对象进行初始化都会先被执行一次。     * 和构造函数的区别:     *             构造代码块是给所有对象进行统一初始化。     *             构造函数时给对应的对象进行初始化。     * 用处:定义给不同对象的共性进行初始化。     */    {        System.out.println("构造代码块");    }}

e.this关键字

  • 用于区分局部变量和成员变量同名情况。
  • this代表它所在的函数所属对象的引用。
  • this代表本类对象。
    private int age;    private String name;    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }
  • 应用:当定义类中功能时,该函数内部要用到调用该函数的对象是,这时使用this来代表使用此对象。凡是本类功能内部使用了本类对象,都用this表示。
class People{    private int age;    /**     * 构造函数     * @param age     */    People(int age)    {        this.age = age;    }    public int getAge()    {        return age;    }    public void setAge(int age)    {        this.age = age;    }    /**     * 比较两个人的年龄是否相等。此处的this代表当前调用的对象的引用也就是p1。     * @param p 人的对象变量     * @return boolean     */    public boolean compare(People p)    {        return this.age == age;    }    public static void main(String[] args) {        People p1 = new People(20);        People p2 = new People(23);        boolean b = p1.compare(p2);        System.out.println("b = " + b);    }}
  • this与构造函数:this用与构造函数的之间互相调用。而且只能定义在构造函数的第一行。因为初始化要先执行
class People{    private int age;    private String name;    /**     * 空构造函数     */    People()    {    }    /**     * 构造函数     * @param age     */    People(int age)    {        this();//调用People()构造函数    }    /**     * 构造函数     * @param age     * @param name     */    People(int age, String name)    {        this(23);//调用People(int age)构造函数        this.name = name;    }

f.static关键字

  • static修饰符,修饰变量、方法和代码块。
  • 当成员被static修饰后,可以用类名直接调用。格式:类名.静态成员。
    static String name;    public static void main(String[] args) {        System.out.println("People.name = " + People.name);    }
  • 特点:随着类的加载而加载,静态随着类的消失而消失,生命周期最长、优先于对象的存在、被所有对象所共享、可以直接被类名所调用。

实例变量和静态成员变量区别:
A.存放位置:(1)静态成员变量随着类的加载而存在方法区中。(2)实例变量随着对象的建立而存在于堆内存中。
B.生命周期:(1)静态成员变量最长,随着类的消失而消失。(2)实例变量随着对象的消失而消失。

静态使用注意点:
A.静态方法只能访问静态成员(方法与变量)。非静态方法即可以访问静态也可以访问非静态。
B.静态方法中不可以定义this、super关键字。因为静态优先于对象存在。
C.主函数是静态的。

静态优缺点:
A.优:对对象的共享数据进行单独空间的存储,节省空间。可以直接被类名调用。
B.缺:生命周期过长、访问出现局限性(只能访问静态)。

静态的使用时间:
* 静态变量(类变量)定义:当对象中的出现对象调用的共享数据时,该数据被静态所修饰存在于方法区中;对象中的特有数据定义成非静态存在于堆内存中。
* 静态函数定义:当类中的某个功能没有访问到非静态数据(对象特有的数据),那么该功能可以定义成静态的(static)。

class People{    String name;    //没有关联到非成员变量name,那么这个函数可以设置成static的,方便后面直接通过类名调用    public static void show()    {        System.out.println("没有访问到成员变量");    }    public static void main(String[] args) {        //调用此方法时,与name没有关系。没有封装进数据。可以不建立对象来调用,设置成static的通过类名调用方便明了。        People.show();    }}

静态代码块

  • 格式:
    static    {        System.out.println("静态代码块");    }
  • 特点:随着类的加载而执行,只执行一次,用于给类进行初始化。并优先于主函数。

g.mian函数

public static void main(String[] args)
  • public:表示全局所有访问权限最大。也就是封装性。
  • static:表示只能通过类调用。主函数随着类的加载就已经存在了。
  • void:主函数没有具体返回值。
  • main:不是关键字,特殊的一个词,可以被JVM识别。
  • String[] args:函数的参数,是一个字符串数组。
    主函数是固定格式:JVM识别

h.对象初始化过程:

People p = new People("zhangsan", 23);

1.因为new用到了People.class,所以会先找到People.class文件并加载到内存中。
2.执行该类中的static代码块,如果有的话。再给People.class类进行初始化。
3.在堆内存中开辟空间,分配内存地址。
4.在堆内存中建立对象的特有属性,并进行默认初始化。
5.对属性进行显示初始化。
6.对对象进行构造代码块初始化。
7.对对象进行对应的构造函数初始化。
8.将内存地址赋给内存中的引用变量p。


i.继承

  • 面向对象特征之二。
  • 把对象间的共性特征进行抽取,类与类之间有关系,最后抽象成一个共性类,被抽取的类的继承自这个共性类就可。减少代码量,提高复用性。
  • 形式:
继承类 extends 被继承类
  • Java只支持单继承。支持多层继承:B继承A,D继承B。D类可以使用A类的功能。
  • 继承关系中类成员的特点:

    A. 变量:如果子类中出现非私有的同名变量时,子类要访问本类中的变量,用this。子类要访问父类中的同名变量,用super,super跟this的使用几乎一致。super代表父类对象的引用,this代表本类对象引用。

/** * Created by Sergio on 2014/11/2. */public class ExtendsDemo1 {    public static void main(String[] args) {        Sun s = new Sun();        s.show();    }}class Parents{    int num = 5;}//子继承父类class Sun extends Parents{    int num = 4;    void show()    {        System.out.println(num);//访问的是子类的变量,相当于this.num        System.out.println(super.num);//碰到同名变量可以使用super关键字访问父类的变量。    }}

B. 函数:当父类出现和子类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容,如同父类的函数被覆盖掉。这也叫做覆盖(重写)。

/** * Created by Sergio on 2014/11/2. */public class ExtendsDemo1 {    public static void main(String[] args) {        Sun s = new Sun();        s.show();    }}class Parents{    int num = 5;    void show()    {        System.out.println("被覆盖");    }}//子继承父类class Sun extends Parents{    int num = 4;    void show()    {        System.out.println(num);//访问的是子类的变量,相当于this.num        System.out.println(super.num);//碰到同名变量可以使用super关键字访问父类的变量。    }}

覆盖注意点:子类覆盖父类,必须保证子类权限大于等于父类权限,才可以叫覆盖,否则编译失败。静态只能覆盖静态。

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

/** * Created by Sergio on 2014/11/2. */public class ExtendsDemo2 {    public static void main(String[] args) {        Sun2 s2 = new Sun2(2);        System.out.println(s2.x);//访问的是父类抽取的x = 4;    }}class Parents2{    int x = 4;    Parents2()    {        System.out.println("fu run");    }    Parents2(int x)    {        System.out.println("x = " + x);    }}//子继承父类class Sun2 extends Parents2{    Sun2()    {        //super();隐式的构造函数        super(1);//根据父类构造函数来指定        System.out.println("zi run");    }    Sun2(int x)    {        super(3);//根据父类构造函数来指定        System.out.println("zi run");    }}

super语句一定定义在子类构造函数的第一行,初始化动作要先做。子类的所有的构造函数,默认都会访问父类中空参数的构造函数,因为子类每一个构造函数的第一行都有一句隐式super();当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问的构造函数。子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。


j. final关键字

  • 解释:最终。修饰符。
  • 修饰的范围:类、函数、变量。
  • 特点:被final修饰的类不可以被继承,为了避免被继承,被子类复写功能。
  • final类:被final修饰的类不可以复写。
  • final变量:被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。
  • 使用的时候。描述事物时,一些数据的出现值是固定的。可以用一个常量来表示。
  • 命名:常量的书写规范所有字母都大写。如果有多个单词定义,每个单词通过”_”链接。P_AI。比如PI。

k. 抽象类

  • 多个类出现相同功能,但是功能主体不同,进行向上抽取,只抽取功能定义,而不抽取功能主题。
  • 定义方式:abstract 类名包含抽象方法和非抽象方法、abstract 方法名();抽象方法只有方法名没有方法内容。
  • 注意:抽象方法只存在于抽象类中。抽象类不可以用new创建对象,因为调用抽象方法没有意义。抽象方法要被使用,必须由子类复写所有的抽象方法后,建立子类对象调用;如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类,因为抽象方法只存在于抽象类中。
  • 抽象类不可以实例化,没意义。

l. 接口

  • 格式:interface 接口名{}。接口中定义常量、方法固定修饰符如下(修饰符可以省略,interface会自动加上。):
    A. 常量:public static final
    B. 方法:public abstract
    接口中的成员都是public。接口中的方法都是抽象的。
/** * Created by Sergio on 2014/11/3. */interface InterfaceDemo {    public static final int NUM = 3;//变量定义    public abstract void intefaceDemo();//方法定义}//接口必须被子类实现用关键字implements,接口可以被多个子类实现。子类也可以继承于一个父类。必须将接口中的所有方法实现因为接口中的方法都是抽象的class InterfaceTest extends ExtendsDemo2 implements InterfaceDemo,InterfaceDemo2....{    @Override    public void intefaceDemo() {    }}

接口是不可以创建对象的,因为有抽象方法存在。需要被子类实现,覆盖接口中的抽象方法后,子类才可以实例化,否则子类是一个抽象类。
接口与接口之间的关系是继承关系,支持多继承关系。

  • 接口特点:
    -. 接口是对外暴露的规则
    -. 接口是程序的功能扩展
    -. 接口可以用来多实现
    -. 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
    -. 接口与接口之间可以有继承关系

m. 多态与关键字instanceof

一. 概念

  • 面向对象特征之三
  • 概念:事物存在的多种体现形态。比如人分为:男人、女人。人 r = new 男人(); 人 r2 = new 女人();

二. 多态扩展性

  1. 多态的体现:父类的引用指向了自己的子类对象(父类)。
  2. 多态的前提:类与类之间有关系,有继承或者实现。
  3. 多态的益处:多态的出现提高了程序的扩展性,通常有前提条件是:存在覆盖。
  4. 多态的弊端:只能使用父类的引用访问父类中的成员。
  5. 多态中成员的特点:
    • 非静态成员函数:
      a. 在编译时期:参与引用型变量所属的类中是否有调用的方法,如果有编译通过,如果没有编译失败。
      b. 在运行时期:参与对象所属的类中是否有调用的方法。
      总结就是:成员函数在多态调用时,编译看左边,运行看右边。
    • 成员变量:
      无论编译和运行:都参考左边(引用型变量所属的类)
    • 静态成员函数(子类不覆盖父类方法,父类走父类,子类走子类。变量也一样。):
      无论编译和运行:都参考左边
/** * Created by Sergio on 2014/11/19. */public class PolymorphicDemo {    public static void main(String[] args) {        //调用子类覆盖父类的eat()方法,有局限性在这点上        function(new Dog());        function(new Pig());    }    //定义共性的功能方法eat()    public static void function(Animal a)    {        a.eat();    }}/** * 集中抽象功能的父类Animal */abstract class Animal{    abstract void eat();}/** * 定义Dog类继承之Animal父类,并且拥有自己的特定功能类houseKeeping(). */class Dog extends Animal{    //覆盖父类eat()方法    public void eat()    {        System.out.println("Dog.eat");    }    //子类特有的方法    public void houseKeeping()    {        System.out.println("看家");    }}/** * 定义Pig类继承之Animal父类,并且拥有自己的特定功能类fat(). */class Pig extends Animal{    //覆盖父类eat()方法    public void eat()    {        System.out.println("Pig.eat");    }    //子类特有的方法    public void fat()    {        System.out.println("养膘");    }}

三. 父类、子类类型转型

/** * Created by Sergio on 2014/11/19. */public class PolymorphicDemo {    public static void main(String[] args) {        //类型提升,向上转型。将Dog类型提升为Animal类型        Animal a = new Dog();        a.eat();        /**         * 如果要调用子类特有的方法操作:强制将父类的引用转成子类类型,向下转型.将父类a引用强制转换成子类类型Dog。         *         * 注意:不能将父类对象转成子类类型。能转换的是父类指向了自己的子类对象时,该引用可以被提升也可以强制转换。         * 多态始终都是子类在作者变化。         */        Dog d = (Dog)a;        d.houseKeeping();        //fun函数调用子类对象的功能        fun(new Dog());        fun(new Pig());    }    //提炼共性函数特征fun(Animal a)    public static void fun(Animal a)    {        a.eat();        /**         * 判断传递进来的子类是那个对象的。使用关键字instanceof,判断左边对象是否属于右边类的实例,返回boolean         * 类型数据。         *         * instanceof是一个二元操作符。使用的前提:1.子类型有限、2.对象需要做比较首先判断是否属于某个类的实例         */        if (a instanceof Dog){            Dog d = (Dog)a;            d.houseKeeping();        }        else if(a instanceof Pig)        {            Pig p = (Pig)a;            p.fat();        }    }}/** * 集中抽象功能的父类Animal */abstract class Animal{    abstract void eat();}/** * 定义Dog类继承之Animal父类,并且拥有自己的特定功能类houseKeeping(). */class Dog extends Animal{    //覆盖父类eat()方法    public void eat()    {        System.out.println("Dog.eat");    }    //子类特有的方法    public void houseKeeping()    {        System.out.println("看家");    }}/** * 定义Pig类继承之Animal父类,并且拥有自己的特定功能类fat(). */class Pig extends Animal{    //覆盖父类eat()方法    public void eat()    {        System.out.println("Pig.eat");    }    //子类特有的方法    public void fat()    {        System.out.println("养膘");    }}

四:小示例

package com.sergio.lianxi;/** * Created by Sergio on 2014/11/20. * * 需求:电脑运行实例。电脑运行基于主板。 */public class PolymorphicDemo2 {    public static void main(String[] args) {        MotherBoard mb = new MotherBoard();        mb.run();        mb.usePCI(new SoundCard());    }}/** * 电脑的各种部件基于电脑主板上的pci接口运行。模拟PCI接口。 */interface PCI{    public void open();    public void close();}//定义主板,运行的基础class MotherBoard{    public void run(){        System.out.println("主板运行");    }    public void usePCI(PCI p)//接口型引用指向自己的子类对象    {        if(p != null)        {            p.open();            p.close();        }    }}/** * 需要运行部件实现方式 */class SoundCard implements PCI{    @Override    public void open() {        System.out.println("声卡运行");    }    @Override    public void close() {        System.out.println("声卡关闭");    }}

2.设计模式


单例设计模式

  • 设计模式概念:解决某一类问题最行之有效的方法,可以重复利用。java有23种设计模式。
  • 单例模式:只对外提供一个实例。在内存中只存在一个对象。
  • 三要素:(1)在类体中需要具有静态的私有的本类型的变量、(2)构造方法必须是私有的,不允许实例化、(3)提供一个公共的静态的入口方法。
package com.sergio.lianxi;/** * 单例模式饿汉式。 * 第一种方式。类一进内存就建立对象。 * Created by Sergio on 2014/10/10. */public class SinglePattern {    private int age;    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    @Override    public String toString() {        return "SinglePattern{" +            "age=" + age +            '}';    }    //以下三个方法是单例使用的必须写法    /**     * 静态私有化本类的成员变量     */    private static SinglePattern instance = new SinglePattern();    /**     * 私有化构造方法,禁止对象实例化     */    private SinglePattern(){}    /**     * 对外提供一个公共的静态入口方法     */    public static SinglePattern getInstance()    {        return instance;    }}class SinglePatternTest{    public static void main(String[] args) {        SinglePattern s1 = SinglePattern.getInstance();        SinglePattern s2 = SinglePattern.getInstance();        s1.setAge(23);        System.out.println("s2 = " + s2);    }}
package com.sergio.lianxi;/** * Created by Sergio on 2014/10/10. * 单例模式懒汉式。也叫延迟加载式。只有调用了getInstance方法时,才建立对象 */public class SinglePattern2 {    private static SinglePattern2 instance = null;    private SinglePattern2(){}    public static synchronized SinglePattern2 getInstance()    {if        if(instance == null)        {            instance = new SinglePattern2();        }        return instance;    }}

注意:开发时候使用饿汉式,也就是第一种。

0 0
原创粉丝点击