java基础(二):面向对象

来源:互联网 发布:php 对象类型 编辑:程序博客网 时间:2024/05/05 21:59

一、成员变量和局部变量

    成员变量:作用于整个类中,存在于堆内存中,因为对象的存在,才在内存中存在。

    局部变量:作用于函数中,存在于栈内存中

二、封装

    封装:是指隐藏对象的属性和实现细节,仅对外提供公共的访问方式

    好处:

        将变化隔离,便于使用,提高重用性,提高安全性

    封装原则:

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

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

        private修饰词修饰(权限修饰符,只能在本类中访问),提供get,set方法。用于修饰成员变量和成员函数。提高代码健壮性

    构造函数

        特点:函数名与类名相同,不用定义返回值类型,不可以写return语句

                    构造函数是在对象已建立就运行,给对象初始化,一个对象建立,构造函数只运行一次

        作用:给对象初始化

        注意:多个构造函数是以重载的形式存在的,

    构造代码块:

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

        和构造函数的区别:构造代码块是给所有对象进行统一初始化的,而构造函数是给对应的对象初始化的。

        注意:当一个类中每一个构造函数都要执行相同的初始化动作时,可以将这个初始化动作放到构造代码快中执行

    this关键字 :

        用于区分局部变量和成员变量同名的情况

        this代表本类对象,代表它所在函数所属对象的引用
        哪个对象在调用this所在的函数,this就代表哪个对象
        this语句(this(name);):用于构造函数间的调用,this语句只能放在构造函数的第一行

//例:class Person{    private String name;    private int age;    Person(){}    Person(String name){        this();        this.name = name;    }    Person(String name,int age){        this(name);        this.age = age;    }}



        原因:假如在定义name的时候初始化了,private String name = "李四";
        构造函数:
            Person(String name){
                this.name = name;
                this();    
            }
            new Person(“张三”);
        一创建对象,会先给name属性赋值“张三”,然后再进行属性的显示初始化“李四”
        取得时候就取不到你初始化的值了。
        被修饰后的成员具备以下特点:
            随着类的加载而加载
                随着类的消失而消失,说明它的生命周期最长
            优先于对象存在
                静态优先存在,对象后存在
            被所有对象共享
            可以直接被类名调用
        注意:
            静态方法只能访问静态成员
            静态中不能写this和super关键字
            主函数是静态的
        调用方式:类名.静态成员。

    实例变量和类变量的区别

        1、存放位置:
            类变量随着类的加载而存在于方法去中
            实例变量随着对象的建立而存在于堆内存中
        2、生命周期
            类变量生命周期最长,随着类消失而消失
            实例变量生命周期随着对象的消失而消失       
        优缺点:
            优点:对对象的共享数据进行单独空间的存储,节省空间,可以直接被类名调用
            缺点:生命周期过长,访问出现局限性

    主函数:

        是一个特殊的函数,作为程序的入口,可以被jvm调用
        主函数的定义:
            public:代表该函数的访问权限最大
            static:主函数随着类的加载就存在了。
            void:没有返回值类型
            main:不是关键字,是个特殊的单词,可以被jvm识别
            (String[] args):函数的参数,
            格式固定:被jvm识别
        静态的使用:
            当方法不访问非静态成员变量时,可将方法静态化,

    静态代码块:

        只执行一次,优先主函数执行用于给类初始化
    对象创建过程:new一个对象:Person p = new Person();
        1、jvm加载类(Person.class)进内存,
        2、静态代码块执行,
        3、堆中开辟空间,分配内存地址值
        4、在堆内存中简历对象的特有属性,并进行默认初始化
        5、显示初始化(定义属性的时候赋的值),
        6、对对象进行构造代码初始化,
        7、构造函数初始化
        8、将内存地址值赋给栈内存中的p变量;

    被静态修饰的(成员方法或成员变量)优先对象存在于方法区中

//单例(static关键字的使用之一)://饿汉式:public class Single {  private Single() {}  private static Single s = new Single();   public static Single getInstance() {      return s;  } }//懒汉式:public class Single { private Single() {} private static Single s = null; public static Single getInstance() { if (s == null) { synchronized(Single.class) { if (s == null) {s = new Single(); } } } return s; }}


java中的方法重写


什么是方法的重写: 
    如果子类对继承父类的方法不满意,是可以重写父类继承的方法的,当调用方法时会优先调用子类的方法。
    重写方法必须和被重写方法具有相同方法名称、参数列表和返回类型。
    重写方法不能使用比被重写方法更严格的访问权限(由于多态)。
继承的初始化顺序


先初始化父类再初始化子类;
先执行初始化对象中的属性,再执行构造方法中的初始化。 
java中的final关键字的使用


final关键字做标识有“最终的”含义。
final可以修饰类、方法、属性和变量。 
    1.修饰类:则该类不允许被继承; 
    2.修饰方法:则该方法不允许被覆盖(重写); 
    3.修饰属性:则该类的属性不会进行隐式的初始化(类的初始化属性必须有值)或在构造方法中赋值; 
    4.修饰变量:则该变量的值只能赋一次值,即为常量。
Java中的super关键字的使用


    super关键字:在对象的内部使用,可以代表父类对象。  
    super的应用 
        1.子类的构造过程当中必须调用其父类的构造方法。 
        2.如果子类的构造方法当中没有显示调用父类的构造方法,则系统会默认调用父类无参的构造方法(通过super关键字)。 
        3.如果显示的调用构造方法,必须写在子类的构造方法的第一行(super();)。 
        4.如果子类构造方法中既没有显示调用父类的构造方法,而父类又没有无参的构造方法,则编译出错。
    java中的Object类

        Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承Object类。
    Object类中的方法,适合所有子类。
        几个重要的方法 
            1.toString()方法: 在Object类中定义toString()方法的时候,返回的是对象的哈希code码(对象地址字符串)。 可以通过重写toString()方法表示出对象的属性。 
            2.equals()方法: 比较的是对象的引用是否指向同一块内存地址。


    抽象练习2:模板方法模式

/** 雇员示例: * 需求:公司中程序员有姓名,工号,薪水,工作内容。 * 项目经理除了有姓名,工号,薪水,还有奖金,工作内容。* 对给出需求进行数据建模。* 分析:* 在这个问题领域中,先找出涉及的对象。 * 通过名词提炼法。 * 程序员: 属性:姓名,工号,薪水、 *       行为:工作。 * 经理: 属性:姓名,工号,薪水,奖金。*       行为:工作。 * 程序员和经理不存在着直接继承关系, 但是程序员和经理却具有共性内容。* 可以进行抽取。因为他们都是公司的雇员* 可以将程序员和经理进行抽取.建立体系.*///描述雇员。abstract 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();// getter setter}// 描述程序员。class Programmer extends Employee {Programmer(String name, String id, double pay) {super(name, id, pay);}public void work() {System.out.println("programmer work");}}// 描述经理。class Manager extends Employee {private int bonus;Manager(String name, String id, double pay, int bonus) {super(name, id, pay);this.bonus = bonus;}public void work() {System.out.println("manager work");}// getter setter}

    static关键字:用于修饰成员(成员变量和成员函数)

三、继承

    特点:

         类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。
         提高代码的复用性。子类继承父类,可以得到父类的全部属性和方法(除了父类中的构造方法)。
         java中只有单继承,没有像c++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
         java中的多继承可以通过接口来实现。 
        提高代码复用性,让类之间产生关系,多态的体现,只支持单继承(接口支持多继承)

//例:class A{void show(){}}class B{void show(){}} class c extends A,B{}class Test{public static void main(String[] args){new C().show();//这里就挂了,不知道调用那个方法了}}

    重写(函数):

        与父类方法同名,同返回值类型,同形式参数,访问权限等于或者大于父类方法的权限,静态只能覆盖静态

    重载和重写的区别:

        重载:只看同名函数的参数列表
        重写:子父类方法要一样(除了里面的逻辑代码)
        super的用法,调用父类一般函数:super.函数名;调用父类构造函数:super();
        super语句必须定义在子类的第一行;
    子类构造函数中super和this语句只能只有一个;
        子类的所有构造函数都会默认访问父类的空参数构造函数(子类所有构造函数第一行都有一句隐式的super();)
        父类中没有空参数的构造函数时,子类必须显示的通过super语句访问父类的构造函数
        子类中至少会有一个构造函数访问父类的构造函数

    问:为什么super和this在构造函数中只能写第一行
         因为初始化动作要先执行

四、抽象

    特点:

        抽象方法一定在抽象类中。
        抽象方法和抽象类都必须被abstract关键字修饰
        抽象类不能创建对象
        抽象类中的方法要被使用,必须有子类复写所有的抽象方法后建立自雷对象调用,如果子类只覆盖了部分抽象方法,那么子类还是一个抽象类

    抽象练习:

/* * 需求:获取一段程序运行时间  * 原理:获取程序开始和结束时间并相减 */abstract class GetTime {public final long getTime() {long start = System.currentTimeMillis();runCode();long end = System.currentTimeMillis();return end - start;}public abstract void runCode();// 让子类做想做的事情,不一定要抽象,可以有默认的方法}class SubTime extends GetTime {@Overridepublic void runCode() {// 方法内的代码自定义try {Thread.sleep(5245);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("SubTime");}public static void main(String[] args) {SubTime st = new SubTime();System.out.println(st.getTime());}}

    接口:

        定义:
            当抽象类的方法都是抽象的,那么这个类可以通过接口的形式来表示
            class:用于定义类
            interface用于定义接口
            子类必须全部覆盖接口方法才能实例化
            一个类可以实现多个接口(就算两个接口中有相同的抽象方法【完全相同,包括返回值和方法名】也可以),并且可以同时实现继承
            接口和接口之间可以实现多继承(注意:当两个接口中有两个抽象方法的方法名相同但是返回值不同的时候,这两个方法要符合重载的形式否则编译失败)

//例:interface A {public abstract int show();}interface B {public abstract double show();}interface C extends A,B{//此时,编译失败//如果A接口和B接口方法名相同,那么可以将两个抽象方法定义到一个接口里,使用重载的形式使其存在}


        接口定义的格式特点:
            接口中常见的定义:常量,抽象方法,静态方法(jdk8才有)
            接口中的成员都有固定的修饰符:
                常量:public static final 类型  名称(名称所有字母大写)
                方法:public abstract 返回值  方法名();
                静态方法:public static 返回值  方法名() {}
        接口的使用:
            类实现接口使用implements关键字,支持类多实现接口,但是只能单继承,如果这个类没有全部实现接口的方法,则这个类是抽象类
            接口之间的继承使用extends关键字,接口之间支持多继承。
        接口的特点
            接口是对外暴露的规则
            接口是程序的功能扩展
            接口可以用来多实现
            类与接口之间是实现关系(implements),而且类可以继承一个类的同事实现多个接口
            接口和接口之间可以有多继承关系

五、多态

    体现:

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

    前提

        必须是类与类之间有关系,要么继承要么实现
        通常还有一个前提:存在覆盖

    好处

        多态的出现大大的提高了程序的扩展性

    弊端

        提高了扩展性,但是只能使用父类的引用访问父类中的成员
        //Animal a = new Cat(); //类型提升,向上转型
        如果想要提升类型,向下转型 Cat c = (Cat)a;

    多态中成员的特点:

        在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有编译通过,没有则编译失败
        在运行时期:参阅对象所属的类中是否有调用的方法
        简单总结就是:成员函数在多态调用时,编译看左边,运行看右边
            多态中,成员变量的特点:无论编译还是运行,都参考左边(引用型变量所属的类)
            多态中,静态成员函数的特点:无论编译,运行,都参考左边
原创粉丝点击