Java中的面向对象

一,面向对象简介

1. 面向对象概念
  • 面向对象是相对面向过程而言,面向对象和面向过程都是一种思想。
  • 面向过程,强调的是功能行为;面向对象,将功能封装进对象,强调具备了功能的对象。
    
2. 基本特征(3个):
  • 封装(Encapsulation):将对象实现细节隐藏,通过一些共用方法来暴露对象的功能;提高类的内聚性,降低了对象之间的耦合性;

    • 私有仅仅是封装的一种表现形式,提供对外访问方式(set和get方法)可以对数据进行操作判断,提高安全性
    • 包也是一种封装形式
      • 包与包之间的类进行访问,被访问的包中的类必须是public的,被访问的包中的类的方法也必须是public的。
  • 继承(Inheritance):类之间共享属性和操作的机制(子类继承父类,直接获得父类的属性和方法,实现类复用);通过extends关键字让类与类之间产生继承关系

    • 特点:
      1. 子类可以直接访问父类中的非私有的属性和行为,子类无法继承父类中私有的内容(方法和变量)
      2. 提高了代码的复用性
      3. Java只支持单继承,不支持多继承,但支持多层继承
    • 继承代码示例:
        class Fu {
            Fu() {
                super();
                show();// 该方法被子类复写,调用的是子类的show方法,此时其成员变量num还未进行显示初始化
            }

            void show() {
                System.out.println("fu show");
            }
        }

        class Zi extends Fu {
            int num = 8;

            Zi() {
                super();// 通过super初始化父类内容时,子类的成员变量并未显示初始化,等super()父类初始化完毕后,才进行子类的成员变量显示初始化
            }

            void show() {
                System.out.println("zi show..." + num);
            }
        }

        class ExtendsDemo {
            public static void main(String[] args) {
                Zi z = new Zi();
                z.show();
            }
        }

运行结果:

  • 多态(Polymorphism):子类对象直接赋给父类变量,运行时依然表现子类特征。

    • 定义:某一类事物的多种存在形态。
    • 作用:多态的存在提高了程序的扩展性和后期可维护性(弊端:前期定义的内容不能调用后期子类的特有内容)
    • 多态时,成员的特点

      • 成员函数(非静态):示例中为method1()、method2()和method3()。

        1. 在编译时期:参考引用型变量所属的类中是否有调用的函数(有,编译通过(method1()被复写,method2()为父类);没有,编译失败(如method3()父类中不存在))。
        2. 在运行时期:参考的是对象所属的类中是否有调用的函数
        3. 简单说:编译看左边,运行看右边。
      • 静态成员函数:实例中的method4()。

        继承中,父类为static的方法无法被覆盖

        1. 编译时:参考的是对象所属的类中是否有调用的函数
        2. 运行时:参考的是对象所属的类中是否有调用的函数
        3. 简单说:编译和运行看左边。
      • 成员变量(静态和非静态):非静态的str1与静态的str2。

        1. 在编译时:参考引用型变量所属的类中是否有调用的成员变量(有,编译通过,没有,编译失败)。
        2. 在运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。
        3. 简单说:编译和运行都参考等号的左边
      • 代码示例:

    /*
    多态中成员(函数和变量)调用特点示例:
    */

    class BaseClass {
        String str1 = "父类非静态成员变量";
        static String str2 = "父类静态成员变量";

        void method1() {
            System.out.println("base method_1");
        }

        void method2() {
            System.out.println("base method_2");
        }

        static void method4() {
            System.out.println("static base method_4");
        }
    }

    class SubClass extends BaseClass {
        String str1 = "子类非静态成员变量";
        static String str2 = "子类静态成员变量";

        //复写父类的method1()方法
        void method1() {
            System.out.println("sub method_1");
        }

        void method3() {
            System.out.println("sub method_3");
        }

        static void method4() {
            System.out.println("static sub method_4");
        }
    }

    class PolymorphismDemo {
        public static void main(String[] args) {
            System.out.println("多态中非静态成员函数调用示例:");
            BaseClass bs = new SubClass();
            bs.method1();       //sub method_1
            bs.method2();       //base method_2
            // f.method3();     //编译不能通过,因父类没有method3()函数
            System.out.println("----------------------- ");
            System.out.println("多态中静态成员函数调用示例:父类");
            bs.method4();       //static base method_4
            System.out.println("--------------------------");
            System.out.println("多态中成员变量调用示例:均为父类");
            System.out.println(bs.str1);    //父类非静态成员变量
            System.out.println(bs.str2);    //父类静态成员变量
        }
    }

以下为运行结果:

  • 开发和设计过程
    • 开发过程:不断创建对象、使用对象和指挥对象做事
    • 设计过程:管理和维护对象之间的关系

二,类与对象

1. 类:

具有共同属性(成员变量)、共同方法(成员函数)的一类事物

内部类

将一个类定义在另一个类的里面,里面那个类就称为内部类(内置类,嵌套类)。

  • 特点
    • 内部类可以直接访问外部类中的成员,包括私有成员
    • 而外部类要访问内部类中的成员必须要建立内部类的对象。
    • 定义时机:分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这时候就定义内部类。
  • 访问格式

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

      格式:
      外部类名.内部类名 变量名=外部类对象.内部类对象;

      e.g.: Outer.Inner in=new Outer().new Inner();

    • 当内部类在成员位置上,就可以被成员修饰符所修饰。比如:private:将内部类在外部类中进行封装当内部类被static修饰后,只能访问外部类中的static成员。出现了访问局限

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

        格式:new Outer.Inner().function();

      2. 在外部其他类中,内部类为静态,直接访问static内部类的静态成员:可以不用创建内部类对象,直接调用

        格式:Outer.Inner.function();

    • 内部类能直接访问外部类中的成员的原因:因为内部类持有了外部类的引用,外部类名.this

  • 注意

    • 当内部类中定义了静态成员,该内部类必须是static的
    • 当外部类中的静态方法访问内部类时,内部类也必须是static的。
    • 内部类定义在局部位置上,也可以直接访问外部类中的成员。同时可以访问所在局部中的局部变量,但必须是被final修饰的。
匿名内部类
  • 定义:内部类的简化写法
  • 前提:内部类可以继承或实现一个外部类或者接口
  • 格式:

    new 父类构造器([实参列表]) 或 接口()
    {
        //匿名内部类的类体部分
    } 
    
抽象类
  • 定义:Java中定义只有功能声明,没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。
  • 格式:修饰符 abstract 返回值类型 函数名(参数列表);

  • 特点:
    - 抽象类和抽象方法必须用abstract关键字来修饰
    - 抽象类不可以被实例化,也就是不可以用new创建对象
    - 抽象类需通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,因此抽象类一定是父类
    - 抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法

接口
  • 概念:当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口。
  • 格式:interface{}

    • 接口中的成员修饰符是固定的:
      1. 成员常量:public static final
      2. 成员函数:public abstract 返回值类型 函数名(参数列表);
  • 特点:

    • 接口中的成员都是公共的权限
    • 接口是对外暴露的规则,接口是程序的功能扩展
    • 接口的出现将“多继承”通过另一种形式体现出来,即“多实现”
    • 一个类在继承另一个类的同时,还可以实现多个接口。
    • 类与类之间是继承关系,类与接口直接是实现关系,可以多实现
    • 接口与接口之间是继承关系,而且接口可以多继承
    • 接口中只能定义抽象方法,必须由子类去实现

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

    • 成员变量(2种):实例Field(不以static修饰)和类Field(以static修饰):

      1. 范围:定义在类中,在整个类中都可以被访问。
      2. 存储:实例Field**堆内存**(随对象的建立而建立,随对象对象被回收而释放);

        类Field(静态变量)存储在方法区(共享数据区)的静态区,随着类的加载而存在,随着类的消失而消失。
      3. 默认初始化值:有。
    • 局部变量(3种):形参(方法签名中定义的变量)、方法局部变量(在方法内定义)和代码块局部变量(在代码块定义)

      1. 范围:只定义在局部范围内(3处)只在所属的区域有效。
      2. 存储:栈内存中(作用的范围结束,变量空间会自动释放)。
      3. 默认初始化值:无。
2. 对象:

类的具体存在,该类事物实实在在存在的个体。

  • 对象的产生:创建对象的根本途径是构造器(特殊的方法),通过new关键字来调用某个类的构造器即可创建这个类的实例。
匿名对象
  • 对象的简化形式(一个没有名字的对象, 创建了一个对象出来,没有赋给一个变量);使用情形:当对对象方法仅一次调用时;作为实际参数进行传递时。

基本数据类型参数及引用数据类型参数传递比较示例:

    //基本数据类型参数传递
    class Demo {
        public static void main(String[] args){
            int x = 3;  //方法局部变量
            show(x);

            /*输出结果为3,因为show()方法中的x为方法局部变量,当主函数调用结束后,show方法出栈。
              show方法参数x也随之出栈。main方法打印x的值。此时x指的是main方法中的x变量的值。
            */

            System.out.println("x=" + x);

        }
        public static void show(int x){
            x = 4;  //方法局部变量
        } 
    }
    //引用数据类型参数传递
    class Demo {
        int x = 3;      //实例Feild,整个类中都可以访问。 
        public static void main(String[] args){
            Demo d = new Demo();
            d.x = 9;
            show(d);   //show方法的参数d和main方法中的变量d同时指向了堆内存中同一个实体对象,堆内存中的实体对象的x属性值变为4。

            /*show方法出栈,show方法参数d也随之出栈,main方法的变量d依然引用着堆内存中的实体对象,
              因此堆内存中的实体对象不会被垃圾回收器清除。
            */

            System.out.println(d.x);//输出结果为4
        }
        public static void show(Demo d){    
            d.x = 4;
        }
    }
2. 两者关系
  • 类是对象的抽象,对象是类的实例。

三,构造器和初始化块

1. 构造器(构造函数)
简介
  • 一个用于创建实例时,执行初始化的特殊方法。

  • 构造器是一个类创建对象的根本途径,系统默认为类提供一个空参的构造器(其执行体为空),当创建一个对象时,系统默认初始化,将基本类型的Field设为0(数值型)或false(布尔型),引用类型的Feild设为null;若想改变这种默认初始化,即可使用构造器来实现。

  • 一旦自定义构造器后,系统将不会提供默认的构造器(一般建议为该类额外编写一个无参的做保留)。

特点
  • 函数名与类名相同
  • 不用定义返回值类型(在构造函数前面加上返回值就只是一般函数了)
  • 没有具体的返回值
  • 多个构造函数是以重载的形式存在的
  • 继承中,子类构造函数执行时,父类构造函数也运行了(原因:在子类的构造函数中,第一行有一个默认的隐式语句:super())
作用
  • 给对象进行初始化。
定义时机:
  • 分析事物,该事物具备一些特性或者行为,就把把这些内容定义到构造函数中,若需要参数进行运算就定义参数。
2. 初始化块(构造代码块)

关于局部代码块:局部代码块可以定义局部变量的生命周期

class IfDemo{
    public static void main(String[] args){
        {
            int m = 89;
            System.out.println("Hello World..." + m);
        }
        /*
         *变量m是局部变量,生命周期仅在局部代码块括号中,当代码执行到局部代码块右括号外,变量m便消失了。
         *局部代码块外的代码当然也就访问不到变量m了。
         */
        //System.out.println("over..." + m);
    }
}
作用
  • 给对象初始化,定义的是不同对象共性的初始化内容对象一建立就运行,而且优先于构造函数执行。
与构造函数区别
  • 构造代码块是给所有对象进行统一初始化,而构造函数是给对应的对象初始化。
代码示例
    class Person {
        private String name;
        private int age;
    //构造代码块,可以给所有对象进行初始化;
        {
            System.out.println("Running!");
        }

        Person() {
            System.out.println("nane="+name+"...age="+age);
        }

        Person(String name) {
            this.name=name;//this 代表它所在函数所属对象的引用:哪个对象在调用this所在函数,this就代表哪个对象,该处为作用一
            System.out.println("nane="+name+"...age="+age);
        }

        Person(String name,int a) {
            //this.name=name; //该句将少打印"name:null...age:0"
            this(name); //this(name),this语句用于构造函数之间的调用,将打印"name:null...age:0",this语句只能定义在构造函数的第一行,因为初始化要先执行,该处为作用二
            age=a;
            System.out.println("nane="+name+"...age="+age);
        }

        public void setAge(int a) {
            if(a>0 && a<130)
            age =a;
            else
                System.out.println("age非法!");
        }

        public int getAge() {
            return age;
        }

        public boolean campare(Person p) {
            return this.age==p.age;//函数内部要用到调用该函数的对象时,这时用this来表示这个对象,该处为作用一
        }
    }

    class PersonDemo2 {
        public static void main(String[] args) {
            Person p1=new Person();
            Person p2=new Person("小明");
            p2.setAge(25);
            System.out.println(p2.getAge());
            Person p3=new Person("小亮",26);
            Person p4=new Person("小贤",24);
            System.out.println(p4.campare(p3));
        }
    }

运行结果:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值