[2021.02.19][Java语言学习]0.面向对象

1. 思想 -> 类

在我的理解中,编程语言的发展经历了几个简要阶段。最初的0101的出现是为了让计算机能够根据电路特征快速的执行一个运算任务;为了不用每次都进行0101的设置,计算机工作者整合不同电路特征的功能作为指令出现了汇编语言,使得每次给计算机下达任务更快;程序越来越大使得用指令编写也变得繁琐,高级编程语言应运而生,拥有着更符合人思维方式的语言特征,减轻了对底层硬件深入理解的负担。

面向对象的语言就属于高级编程语言的一种,背后的思维方式是对物质本身进行抽象定义。自然世界是由物体构成的,人是一个物体,电脑是一个物体,甚至空气也是以气体形式存在的物体。面向对象也是这样,程序是用代码抽象表示的物体,也由其他抽象物体所构成。

在编写面向对象程序的时候,程序员充当着自然世界“上帝”的角色,可以随意创造物体。从这个角度出发,当我们需要某样(抽象的)物体的时候创造一个就行了,需要一台电脑造一个,需要桌子造一个,需要一个小baby造一个,需要一个女朋友造一个... 前提是有这个物体的模板或者是蓝图。

创造的前提是有这个物体的模板或者蓝图,所以在创造之前还需要设计物体的蓝图。从人的思维方式角度,围绕一个物体需要回答三个问题,是什么为什么怎么做。既然程序代表的是抽象的物体,那也需要回答这三个问题。关于是什么,物体可以概括为特征和功能;“为什么要设计”的重要性在编程中是浮动比较大的,实际生产中由需求决定,而在学习或尝试中往往是不需要理由的,因为程序员此时充当的角色是“上帝”;关于怎么做,程序员需要利用编程语言提供的语法完成“是什么”中约定的特征和功能。

针对同一类物种,一个模板或者蓝图就足够了。例如,普通人与普通人之间,区别在于身高,性别,年龄等等,但是每个人都有身高,性别,年龄等特征。

对应到Java中,设计蓝图即为编写类,创造物体即为根据类创建实例。

2. 类的蓝图

从创造抽象物体的思想中已经可以看出,类就代表了抽象物体的蓝图。那么类具体要怎么设计?从对“是什么”的回答中能看出类需要特征和功能。
Note:特征、属性、变量,代表的是同样的意思,功能、方法、函数也是如此。

2.1 声明类

打开记事本,写下如下的代码,就创建了一个名称是OneClass的类,这是类最简单的形式。

class OneClass{

}

除此之外,类还有修饰符继承实现接口

  1. 修饰符用于指定类的可获取性,包括public,private, protected,package-private,final。可获取性简单的举个例,一个甜品店有试吃甜品和付款商品,试吃的所有人都可以随意吃,这就是public,付款的只能在店内挑选购买,那这就是private。

  2. A类可以继承也可以被继承,相对于被继承的类,A类是子类,相对于继承A类的类,A类是父类,所谓B类继承A类就是在类别划分中B类属于A类的子集。

    同时,谈到继承就要谈到共性和特性,如果此时C类也继承A类,那么A类中的特征和功能就是B和C所共有的,但B和C又有各自的特性。例如,汽车继承车,自行车也继承车,汽车和自行车所共有的是速度、轮胎等等,但是汽车特有油门,自行车特有脚踏。至于如何规定类与类之间的继承关系,那就要看业务的粒度需求了。实例代码如下,之所以不用把Vehicle中的功能在Car中写出来,是因为已经隐式的继承过来了。

    class Vehicle{
        void forward(){}
        void back(){}
    }
    
    class Car extends Vehicle{
    }
    

    在内存当中,继承的编排如下图


    静态和继承.jpg
  1. 接口就是功能,或者说规定了类需要实现的功能。再拿汽车来举例子,汽车继承自车,那么车的前进后退功能肯定也是继承过来了。但是现在出现了一个飞行汽车,那这到底是继承汽车还是继承飞机呢?这种情况,可以规定一个飞行功能的接口,使用汽车实现这个接口,那么飞行的功能汽车也有了。问题又来了,现在出现一个水陆空三栖的车咋办?再实现一个游泳的接口就可以啦。实例代码如下:
    interface AirPlane{
        void fly();
    }
    
    interface Boat{
        void swim();
    }
    
    class Vehicle{
        void forward(){}
        void back(){}
    }
    
    class Car extends Vehicle implements AirPlane, Boat{
        void fly(){
            //todo
        }
        void swim(){
            //todo
        }
    }
    

2.2 定义类的属性--变量

类声明好了,也就是蓝图的框架搭好了,就该开始搭建“是什么”的内容了,首先就是类的变量,也叫特征、属性等。

类的变量从4个方面介绍:

  • 变量定义
  • 变量类型
  • 初始化
  • 修饰符(与类的功能一致,统一在修饰符进行介绍)
  1. 类中变量的定义如下:

    modifier1 modifier2... variableType variableName
    
  2. 类中的变量包括成员变量、局域变量、参数变量,成员变量又可以细分为类变量和实例变量。
    类变量是与类同在的,所有创建的对象不拥有类变量,然而在创建对象的时候,每个对象都复制一份单独的实例变量。类变量不会继承给子类,可以理解为子类是一种特殊的父类,所以同一个家族类中的静态变量(类变量)是共享的。

    static int a; //类变量
    int b; //实例变量
    

    局域变量是在功能中新建的暂时变量,等功能执行完毕就不复存在。

    {
        int c;
    }
    

    参数变量是功能的初始状态,作为功能参数或者称为函数参数而存在。

    void print(String string){
        //do something with string
    }
    
  3. 变量的初始化针对的是类中成员变量的初始化,有三种方式。

    • 第一种,通过=的形式,例如int a = 10;
    • 第二种,通过静态代码块对类变量进行初始化,例如static{a = 10;},一个类中可以有很多个static代码块,运行的时候按顺序执行;或者使用静态函数。
    • 第三种,通过无名称代码块对实例变量进行初始化,例如{a = 10;},无名称代码块会被插入到构造函数中,这样也可以将无名称代码块当做所有构造函数都共享的代码块存在;或者使用final函数,使用final函数的好处是不可以被子类重写。

2.3 定义类的功能--方法/函数

除了类的属性,类还需要拥有功能,就是类的方法。类的方法又称为函数,包括构造函数和普通函数。
类的函数从五个方面进行介绍:

  • 定义
  • 类型(构造、成员函数、实例函数)
  • 参数
  • 返回值
  • this引用
  1. 函数定义包括五个部分,修饰符,返回值类型,名称,参数,和异常抛出,如下:

    Modifier1 Modifier2... ReturnType MethodName(ParameterType Parameter1,...) throws Exception1{
    }
    
  2. 函数的类型包括构造函数,静态函数(成员函数),实例函数。

    • 构造函数:在创建抽象物体(对象)的时候,需要给对象的属性进行初始的设置,此时就通过构造函数在内存区域进行设置。构造函数可以重载,也就是可以有好多个构造函数,通过不同的参数类型的排列组合进行区分。
    • 静态函数是通过函数名调用,并且无法继承,由所有的实例共享。也可以通过实例调用,但是静态函数不需要实例就可以调用。通常静态函数作为辅助函数,或者作为静态变量的getset函数。
    • 实例函数实际上也是所有的实例共享的一个代码段,但是需要通过实例来进行调用,所谓通过实例进行调用,也就是实例在运行某个方法的时候会开辟不同的空间,各自执行。
  3. 函数的参数可以是引用类型,例如数组,String等类型,也可以是基本数据类型。如果参数本身是不确定的,也可以使用Type... name作为参数,例如String... strings,那么在函数进行解析的时候,仍然是将参数作为数组进行解析,不过此时需要在函数中注意数组的长度。在使用引用类型作为参数的时候,如果该引用类型的参数重新指向一个新创建的对象,但是没有将该参数作为返回值返回,那么在程序段外部,这个重新指向是不成功的。具体的引用类型将在使用实例部分介绍。

  4. 返回值代表了函数最后的输出结果。返回类型为基本数据类型的时候是值返回,如果返回的是某个对象的时候,采用的是引用返回。
    返回值在三种情况下会发生

    • 执行完函数
    • 执行到return语句
    • 抛出异常
  5. this引用是对当前实例的引用,可以使用在两个地方。

    • 第一个是在方法内部,当参数中的变量和实例变量同名的时候,使用this引用当前实例可以指向实例变量。
    • 第二个是在一个类有多个重载构造函数的时候,this可以用于调用其他构造函数。Note:需要注意的是,在使用this,super调用构造函数的时候,this、super语句需要放在第一句。这是为了保证,在其他构造函数有可能操作到父类构造函数的情况下,优先执行父类的构造函数。

2.4 类的修饰符

类的修饰符包括两种:

  • 访问控制符
  • static 和 final
  1. 访问控制符分为两级

    • 第一级为文件开头的类的控制符,包括public和默认的package-private,public对所有类都开放,默认的只是在包内开放。
    • 第二级为类内部的控制符,包括public,private,protected,package-private四种。下图的表格表示了不同修饰符所代表的的成员可访问范围。
    修饰符 类内部 包内部 子类 公开
    public Y Y Y Y
    protected Y Y Y N
    package-private Y Y N N
    private Y N N N
  1. static表示静态,主要影响是可以使用类名直接调用,不可以用来修饰文件开头的类。使用final表示所修饰的成员是不可以改变的,用来修饰类的时候,表明该类是不可以被继承的

3 类的实例

3.1 创建实例

创建一个实例,包括三个部分:声明,实例化,初始化。

  • 声明是通过 类名 + 实例引用名称实现,此时不会给这个实例分配地址空间;
  • 实例化是通过new实现,此时给实例分配了地址空间,并且也将地址给到了引用对象;
  • 初始化是通过调用构造函数实现,此时对实例的地址空间中的变量就行初始化赋值和运算。
TypeName instanceName = new TypeName(Parameters...)

创建的实例,在代码中只是以引用形式存在,instanceName实际上是一个内存单元里面存放了实例的首地址,通过这种方式对实例进行引用。这也解释了函数参数部分提到的一个结论。

3.2 使用实例

使用实例的时候通过实例引用名称可以调用实例的方法。实例本身是不存储方法的,当实例要调用类中定义的某个方法的时候,会开辟一个新的内存空间,将这个方法加载进去。所以不同实例在运行同一个函数其实是在不同的内存空间运行,不会产生冲突,就相当于用加载时间换实例存储的空间。

正如创建实例中提及到,代码中不存在实例本身的地址,存在的都是对实例的引用。当某个实例不再有引用对象指向它时,就有可能被Java自带的garbage collector收集。所以释放一个实例可以通过手动将引用对象指向null实现instanceName=null。那么类似函数参数中所说的函数中的引用呢?调用函数是一个压栈过程,在函数运行结束时,函数出栈,也就是说此时函数中的引用就不再存在了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容