Java基本系列1:Java面向对象
2019-11-18杂谈搜奇网29°c
A+ A-该系列博文会通知你怎样从入门到进阶,一步步地进修Java基本学问,并上手举行实战,接着相识每一个Java学问点背地的完成道理,更完整地相识悉数Java手艺体系,组成本身的学问框架。
概述:
Java是面向对象的递次设想言语,Java言语供应了定义类、成员变量、要领等最基本的功用。类可被认为是一种自定义的数据范例,能够运用类来定义变量,统统运用类定义的变量都是援用变量,它们将会援用到类的对象。类用于形貌客观天下里某一类对象的配合特征,而对象则是类的细致存在,Java递次运用类的组织器来建立该类的对象。
对象和类:
Java是面向对象的递次设想言语,类是面向对象的主要内容,能够把类当做一种自定义范例,能够运用类来定义变量,这类范例的变量统称为援用变量。也就是说,统统类是援用范例。对象是由类建立出来的,能够说类时对象的笼统,对象是类的实例。
对象的观点:
Java 是面向对象的编程言语,对象就是面向对象递次设想的中间。所谓对象就是实在天下中的实体,对象与实体是一一对应的,也就是说现实天下中每一个实体都是一个对象,它是一种细致的观点。对象有以下特征:
- 对象具有属性和行动。
- 对象具有变化的状况。
- 对象具有唯一性。
- 对象都是某个种别的实例。
- 统统皆为对象,实在天下中的统统事物都能够视为对象。
面向对象与面向历程:
1、面向历程:
面向历程是一种以事宜为中间的编程头脑,编程的时刻把解决问题的步骤剖析出来,然后用函数把这些步骤完成,在一步一步的细致步骤中再按递次挪用函数。
我们以五子棋为例来解释一下面向历程是怎样解决问题的:
下过五子棋的同砚都晓得,首先要找两个人,然后把棋谱摆放好,个中一方手持黑棋,另一方手持白旗,寻常商定白棋先动,然后黑棋在动,如许每人一步,直到某一方先凑成五子一条线便为赢。这是我们寻常下五子棋的历程,那末用面向历程该怎样示意呢?
我们能够将下五子棋的历程笼统成以下步骤:
(1)最先游戏(2)黑子先走(3)绘制画面(4)推断胜负(5)轮到白子(6)绘制画面(7)推断胜负(8)返回步骤(2) (9)输出末了效果。
接着我们用面向历程来完成五子棋这一递次:
下五子棋{ 最先游戏(); 黑子先走(); 绘制画面(); 推断胜负(); 轮到白子(); 绘制画面(); 推断胜负(); 返回到 黑子先走(); 输出末了效果; }
可见,面向历程一向关注的是怎样一步一步地推断棋局胜负的,经由过程控制代码,从而完成函数的递次实行。
2、面向对象:
一种基于面向历程的新编程头脑,望文生义就是该头脑是站在对象的角度思索问题,我们把多个功用合理放到差别对象里,强调的是具有某些功用的对象。
具有某种功用的实体,称为对象。面向对象最小的递次单位是:类。面向对象越发相符通例的头脑体式格局,稳定性好,可重用性强,易于开辟大型软件产品,有优越的可保护性。
Java编程头脑一书中有一段对面向对象的总结异常清晰到位,可谓是面向对象的英华地点:
1、万物皆对象
2、递次时对象的鸠合,它们经由过程发送音讯来示知相互所须要做的
3、每一个对象都有本身的由其他对象所组成的存储
4、每一个对象都具有其范例
5、某一特定范例的统统对象都能够吸收一样的音讯
3、二者优瑕玷比较:
(1)、面向历程:
长处:
流程化使得编程使命明白,在开辟之前基本斟酌了完成体式格局和终究效果,细致步骤清晰,便于节点剖析。
效力高,面向历程强调代码的短小精悍,擅长连系数据构造来开辟高效力的递次。
瑕玷:
须要深切的思索,消耗精神,代码重用性低,扩大能力差,后期保护难度比较大。
(2)、面向对象:
长处:
构造清晰,递次是模块化和构造化,越发相符人类的头脑体式格局;
易扩大,代码重用率高,可继续,可掩盖,能够设想出低耦合的体系;
易保护,体系低耦合的特征有利于削减递次的后期保护事情量。
瑕玷:
开支大,当要修正对象内部时,对象的属性不许可外部直接存取,所以要增加许多没有其他意义、只担任读或写的行动。这会为编程事情增加累赘,增加运转开支,而且使递次显得痴肥。
机能低,因为面向更高的逻辑笼统层,使得面向对象在完成的时刻,不能不做出机能上面的捐躯,盘算时候和空间存储大小都开支很大。
面向对象的三大特征:
概述:
1、继续:
继续是面向对象的三大特征之一,也是完成软件复用的主要手腕。Java的继续具有单继续的特征,每一个子类只要一个直接父类。
2、封装:
封装(Encapsulation)是面向对象的三大特征之一,它指的是将对象的状况信息隐蔽在对象内部,不许可外部递次直接接见对象内部信息,而是经由过程该类所供应的要领来完成对内部信息的操纵和接见。
封装是面向对象编程言语对客观天下的模仿,在客观天下里,对象的状况信息都被隐蔽在对象内部,外界没法直接操纵和修正。比方说一个人的岁数,岁数只会跟着时候的流逝而逐步增进,不能随便修正人的岁数。对一个类或对象完成优越的封装,能够完成以下目标。
3、多态:
Java援用变量有两个范例:一个是编译时范例,一个是运转时范例。编译时范例由声明该变量时运用的范例决议,运转时范例由现实赋给该变量的对象决议。假如编译时范例和运转时范例不一致,便能够涌现所谓的多态(Polymorphism)。
多态的作用是消弭范例之间的耦合关联。
详解:
一、继续:
1、继续的观点:
递次来源于生活,也为生活所用。我们先从生活中的例子来看一下什么是继续:
如今有一个农场主,家有良田万顷,每一年收入许多,他有一个儿子,就是我们口中的富二代。有一天农场主不幸作古了,那末他部下的农田和财产都是谁的了,毫无疑问,当然是他儿子的了(假如你好好勤奋,未来你儿子有很大机会是富二代哦)。那末他儿子原本一贫如洗,如今顷刻间多了须要Money,农田,屋子等等,也就是具有了他父亲的统统物质财产,这个我们就称之为继续。
Java的继续经由过程extends关键字来完成,完成继续的类被称为子类,被继续的类被称为父类,有的也称其为基类、超类。父类和子类的关联,是一种寻常和特别的关联。比方生果和苹果的关联,苹果继续了生果,苹果是生果的子类,则苹果是一种特别的生果。
class Fruit{ public double weight; public void info() { System.out.println("我是一个生果,重"+weight+"g"); } } public class Apple extends Fruit{ public static void main(String[] args) { //建立Apple对象 Apple apple=new Apple(); //Apple对象本身并没有weight成员变量 //然则Apple的父类用于weight变量,所以Apple也能够方位 apple.weight=88; apple.info(); } }
效果:我是一个生果,重88.0g
2、重写父类的要领:
子类扩大了父类,子类是一个特别的父类。大部分时刻,子类总是以父类为基本,分外增加新的成员变量和要领。但有一种状况破例:子类须要重写父类的要领。比方鸟类都包括了飞行要领,个中鸵鸟是一种特别的鸟类,因而鸵鸟应该是鸟的子类,因而它也将从鸟类取得飞行要领,但这个飞行要领显著不适合鸵鸟,为此,鸵鸟须要重写鸟类的要领。
//父类 class Bird{ public void fly() { System.out.println("我在天空自在的飞行"); } } public class Ostrich extends Bird { //重写Bird的fly要领 public void fly() { System.out.println("我只能在地上奔驰"); } public static void main(String[] args) { //建立Ostrich对象 Ostrich ostrich=new Ostrich(); ostrich.fly(); } } 效果:我只能在地上奔驰
重写时须要注重:
1、返回值范例
2、要领名
3、参数范例及个数
都要与父类继续的要领雷同,才叫要领的重写。
重写与重载的辨别:
重写:相对继续而言,子类中对父类已存在的要领举行辨别化的修正。
重载:在一致个类中处置惩罚差别数据的多个雷同要领名的多态手腕。重载要领名雷同,参数列表差别。
3、继续的初始化递次:
先思索一下下面代码的输出效果:
class Animal{ public Animal() { System.out.println("我是父类动物"); } } class Humanity extends Animal{ public Humanity() { System.out.println("我是父类人类"); } } public class Student extends Humanity{ public Student() { System.out.println("我是子类门生"); } public static void main(String[] args) { Student student=new Student(); } }
不要看效果,本身先思索一下
输出效果:

是不是是和你思索的效果一样,不一样的同砚接着往下看:
Java中继续初始化递次以下:
1、初始化父类再初始化子类
2、先实行初始化对象中属性,再实行组织要领中的初始化。
基于上面两点,我们就晓得实例化一个子类,java递次的实行递次是:
父类对象属性初始化---->父类对象组织要领---->子类对象属性初始化—>子类对象组织要领
下面放上一张抽象的图:
4、final关键字:
final 关键字可用于润饰类、变量和要领,final关键字有点相似C#里的sealed关键字,用于示意它润饰的类、要领和变量不可转变。
final润饰变量时,示意该变量一旦取得了初始值就不可被转变,final既能够润饰成员变量(包括类变量和实例变量),也能够润饰局部变量、形参。有的书上引见说final润饰的变量不能被赋值,这类说法是毛病的!严厉的说法是,final润饰的变量不可被转变,一旦取得了初始值,该final变量的值就不能被从新赋值。因为final变量取得初始值以后不能被从新赋值,因而final润饰成员变量和润饰局部变量时有肯定的差别。
1、final润饰变量:
☆:final润饰成员变量:一旦有了初始值,就不能被从新赋值。final润饰的成员变量必需由递次显现的指定初始值。final润饰类变量必需在静态初始化块中指定初始值或声明该类变量时指定初始值,而且只能在两个处所个中之一指定;final润饰实例变量必需在非静态初始化块、声明该实例变量或组织器中指定初始值,而且只能在三个处所的个中之一指定。
☆:final润饰局部变量:体系不会对局部变量举行初始化,局部变量必需由递次员显式初始化。因而运用final润饰局部变量时,既能够在定义时指定默许值,也能够不指定默许值。
☆:final润饰基本范例变量与援用范例变量辨别:当运用final润饰基本范例变量时,不能对基本范例变量从新赋值,因而基本范例变量不能被转变。但关于援用范例变量而言,它保留的仅仅是一个援用,final只保证这个援用范例变量所援用的地点不会转变,即一向援用一致个对象,但这个对象完全能够发作转变。
import java.util.Arrays; public class FinalTest { public static void main(String[] args) { //final润饰数组变量,arr只是一个援用变量 final int[] arr= {3,90,33,12}; System.out.println(Arrays.toString(arr)); //对数组举行排序,正当 Arrays.sort(arr); System.out.println(Arrays.toString(arr)); //对数组元素举行赋值,正当 arr[2]=109; System.out.println(Arrays.toString(arr)); //下面语句对arr从新赋值,不法 //arr=null; } }
2、final润饰要领:
final润饰的要领不可被重写
3、final润饰类:
final润饰的类不能够有之类
5、this关键字:
this是本身的一个对象,代表对象本身,能够理解为:指向对象本身的一个指针。
this的用法:
1、一般的直接援用
2、形介入成员名字重名,用this来辨别
public class Student{ String username; String password; public Student(String username,String password) { //this 代表当前对象 也就是下面的student this.username=username; this.password=password; } public static void main(String[] args) { Student student=new Student("jack","123"); } }
3、援用组织函数,这个放在super关键字中说
6、super关键字:
super能够理解为是指向本身超(父)类对象的一个指针,而这个超类指的是离本身近来的一个父类。
super的用法:
1、一般的直接援用:与this相似,super相称因而指向当前对象的父类
super.name:援用父类的变量
super.add():援用父类的要领
2、子类中的成员变量或要领与父类中的成员变量或要领同名:
class Humanity{ public void eat() { System.out.println("动物吃肉"); } } public class Student extends Humanity{ public void eat() { //super挪用父类中的同名要领 super.eat(); System.out.println("人用饭"); } public static void main(String[] args) { Student student=new Student(); student.eat(); } }
效果:
动物吃肉 人用饭
3、援用组织函数:
super(参数):挪用父类中的某一个组织函数(应该为组织函数中的第一条语句)。 this(参数):挪用本类中另一种情势的组织函数(应该为组织函数中的第一条语句)。class Humanity{ public Humanity() { System.out.println("父类无参组织"); } public Humanity(String s) { System.out.println("父类有参组织======"+s); } } public class Student extends Humanity{ public Student() { super();//挪用父类的无参组织要领 System.out.println("子类无参组织"); } public Student(String s) { super(s);//挪用父类的有参组织 System.out.println("子类的有参组织======"+s); } public Student(String username,String password) { this(username);//挪用本类的有参组织 System.out.println("子类带两个参数的组织函数======"+username+"======"+password); } public static void main(String[] args) { Student student=new Student(); Student student2=new Student("小明"); Student student3=new Student("小明","123"); } }
输出效果:
父类无参组织 子类无参组织 父类有参组织======小明 子类的有参组织======小明 父类有参组织======小明 子类的有参组织======小明 子类带两个参数的组织函数======小明======123
二、封装:
1、封装的观点与长处:
封装(Encapsulation)是面向对象的三大特征之一,它指的是将对象的状况信息隐蔽在对象内部,不许可外部递次直接接见对象内部信息,而是经由过程该类所供应的要领来完成对内部信息的操纵和接见。
封装是面向对象编程言语对客观天下的模仿,在客观天下里,对象的状况信息都被隐蔽在对象内部,外界没法直接操纵和修正。就如方才说的Person对象的age变量,只能跟着光阴的流逝,age才会增加,一般不能随便修正Person对象的age。对一个类或对象完成优越的封装,能够完成以下目标。
- 隐蔽类的完成细节。
- 让运用者只能经由过程事前预定的要领来接见数据,从而能够在该要领里到场控制逻辑,限定对成员变量的不合理接见。
- 可举行数据搜检,从而有利于保证对象信息的完整性。
- 便于修正,进步代码的可保护性。
为了完成优越的封装,须要从两个方面斟酌。
- 将对象的成员变量和完成细节隐蔽起来,不许可外部直接接见。
- 把要领暴露出来,让要领来控制对这些成员变量举行平安的接见和操纵。
2、接见润饰符:
Java供应了3个接见润饰符:public、protected和private,别的另有一个默许的润饰符default,Java的接见控制级别以下图所示:
下面来细致引见一下四个接见润饰符:
- private(当前类接见权限):假如类里的一个成员(包括成员变量、要领和组织器等)运用private接见控制符来润饰,则这个成员只能在当前类的内部被接见。很显然,这个接见控制符用于润饰成员变量最合适,运用它来润饰成员变量就能够把成员变量隐蔽在该类的内部。
- default(包接见权限):假如类里的一个成员(包括成员变量、要领和组织器等)或许一个外部类不运用任何接见控制符润饰,就称它是包接见权限的,default 接见控制的成员或外部类能够被雷同包下的其他类接见。关于包的引见请看5.4.3节。
- protected(子类接见权限):假如一个成员(包括成员变量、要领和组织器等)运用protected接见控制符润饰,那末这个成员既能够被一致个包中的其他类接见,也能够被差别包中的子类接见。在一般状况下,假如运用protected来润饰一个要领,一般是愿望其子类来重写这个要领。
- public(大众接见权限):这是一个最宽松的接见控制级别,假如一个成员(包括成员变量、要领和组织器等)或许一个外部类运用public接见控制符润饰,那末这个成员或外部类就能够被统统类接见,不论接见类和被接见类是不是处于一致个包中,是不是具有父子继续关联。
控制了接见润饰符后,我们就能够来运用封装了。
public class Person { private String username; private Integer age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
上述代码Person类中有两个成员变量username和age,它们都是私有变量,外部不能接见,然则供应了get和set要领,经由过程这两个要领便能够修正和猎取Person类中的相干数据,这就是封装
3、java中的包是什么?
记得我上初中的时刻,班级有两个同名的同砚,都叫王健,先生每次叫王健的时刻他俩不晓得叫的是谁,厥后加上性别辨别,一个叫男王健,一个叫女王健,此次辨别开。
那末我们在java中会不会碰到这类状况呢?当然会,比方就Person这个类而言,在一个大型项目中,多人合作开辟,你写了一个类叫Person,我也写个类叫Person,那末该怎样辨别这两个类呢?总不能一个叫男Person,一个叫女Person吧,哈哈。这时刻java就引入了包的机制,许可在类名前面加上一个前缀来限定这个类,供应了类的多层定名空间
注重:
1、package语句必需作为源文件的第一条非解释性语句,一个源文件只能指定一个包,即只能包括一条package语句,该源文件中能够定义多个类,则这些类将悉数位于该包下。
2、假如没有显式指定package语句,则处于默许包下。在现实企业开辟中,一般不会把类定义在默许包下,但本书中的大批示例递次为了简朴起见,都没有显式指定package语句。
3、一致个包下的类能够自在接见
三、多态:
1、多态的观点:
多态是指许可差别类的对象对一致音讯做出相应。即一致音讯能够依据发送对象的差别而采纳多种差别的行动体式格局。(发送音讯就是函数挪用)
2、多态的作用:
消弭范例之间的耦合关联。
3、多态发生的前提:
1、要有继续;
2、要有重写;
3、父类援用指向子类对象。
4、多态的长处:
1、可替代性(substitutability)。多态对已存在代码具有可替代性。比方,多态对圆Circle类事情,对其他任何圆形几何体,如圆环,也一样事情。
2、可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继续性,以及其他特征的运转和操纵。现实上新加子类更轻易取得多态功用。比方,在完成了圆锥、半圆锥以及半球体的多态基本上,很轻易增加球体类的多态性。
3、接口性(interface-ability)。多态是超类经由过程要领署名,向子类供应了一个配合接口,由子类来完美或许掩盖它而完成的。如图8.3 所示。图中超类Shape划定了两个完成多态的接口要领,computeArea()以及computeVolume()。子类,如Circle和Sphere为了完成多态,完美或许掩盖这两个接口要领。
4、灵活性(flexibility)。它在运用中表现了灵活多样的操纵,进步了运用效力。
5、简化性(simplicity)。多态简化对运用软件的代码编写和修正历程,尤其在处置惩罚大批对象的运算和操纵时,这个特征尤其凸起和主要。
Java中多态的完成体式格局:接口完成,继续父类举行要领重写,一致个类中举行要领重载。
5、典范的多态案例:
class Animal{ public void eat() { } } class Cat extends Animal { public void eat() { System.out.println("吃鱼"); } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } public void kanJia() { System.out.println("看家"); } } public class AnimalTest { public static void main(String[] args) { Animal cat=new Cat();//向上转型 cat.eat(); Animal dog=new Dog(); dog.eat();
//Cat c=(Cat)cat;//向上转型 } }
Animal是父类,它有两个之类离别是Dog和Cat,之类离别重写了父类的eat要领。
输出效果:
吃鱼 吃骨头
从输出效果能够看出,一样都是Animal,然则却有差别的行动表现,这就是多态
6、向上转型和向下转型:
1、向上转型:就以上述的父类Animal和一个子类Dog来申明,当父类的援用能够指向子类的对象时,就是向上范例转换:Animal cat=new Cat();
2、向下转型:向下范例转换(强迫范例转换),是大范例转换到小范例(有风险,能够涌现数据溢出)。比方:Cat c=(Cat)cat
7、重写和重载:
重写:父类与子类之间的多态性,对父类的函数举行从新定义。假如在子类中定义某要领与其父类有雷同的称号和参数,我们说该要领被重写 (Overriding)。在Java中,子类可继续父类中的要领,而不须要从新编写雷同的要领。
重载:要领重载是让类以一致的体式格局处置惩罚差别范例数据的一种手腕。多个同名函数同时存在,具有差别的参数个数/范例。重载是一个类中多态性的一种表现。
重载发作在一个类当中,重写发作在两个类当中,然则这两个类是父子类的关联。