黑马程序员---面向对象上(封装,继承,多态)

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流!

 

 

面向对象(Object-Oriented,简称OO)就是一种常见的程序结构设计方法。
面向对象思想的基础是将相关的数据和方法放在一起,组合成一种新的复合数据类型,然后使用新创建的复合数据类型作为项目的基础。

 面向对象思想:面向对象是基于面向过程的编程思想

面向对象是一个很抽象的概念,它相对面向过程而言。

过程与对象都是一种解决问题的思想。

面向过程:强调的是功能行为,一种过程,先干啥,再干啥;

面向对象:将功能封装到对象里,强调的是具备某功能的对象;

按照面向对象的思想,可以把任何的东西看做对象!

面向对象思想特点:
 是一种更符合我们思想习惯的思想
 可以将复杂的事情简单化
 将我们从执行者变成了指挥者

面向对象的三个特征:

封装(Encapsulation);

继承(Inheritance);

多态(Polymorphism)

我的总结:

面向过程:强调的是具体的功能实现;(执行者)

面向对象:强调的是具备功能的对象。(管理者)

 

类与对象
(class)Java语言的最小编程单位,也是设计和实现Java程序的基础,本部分将深入介绍类的相关知识。
类的概念
类是一组事物共有特征和功能的描述。类是对于一组事物的总体描述,是按照面向对象技术进行设计时最小的单位,也是组成项目的最基本的模块。类的概念是抽象的,类似于建筑设计中的图纸,是对于现实需要代表的具体内容的抽象。类只包含框架结构,而不包含具体的数据。所以类代表的是总体,而不代表某个特定的个体。

 对象:是该类事物的具体体现

举例:
 类 学生
 对象 班长就是一个对象

 

我的总结:类是抽象的,对象是具体的,实实在在的!

类的定义:

[修饰符] class 类名{

   1~n个构造方法;

0~n个字段;

0~n个方法

}

定义类,其实就是定义类里面的对象

对象包含:

状态;(属性)

功能、行为;(方法)

通过类来描述对象;

状态--------成员变量;

功能、行为——方法;

Eg

class Person{

//属性

<span style="font-size:18px;">class Person{
 
//属性
 
private String name;
 
private int age;
 
private int sal;
 
//方法
 
public void show(){
 
System.out.println("个人情况:"+name+age+sal);
 
}
 
}
</span>

 

 


变量的定义
 成员变量: 这个变量是否属于事物中的属性
 特点:变量的使用范问越小越好成员变量和局部变量的区别:
 在类中的位置不同
  成员变量 类中方法外
  局部变量 方法内或者方法声明上
 在内存中的位置不同
  成员变量 堆内存
  局部变量 栈内存
 生命周期不同
  成员变量 随着对象的存在而存在,随着对象的消失而消失
  局部变量 随着方法的调用而存在,随着方法的调用完毕而消失
 初始化值不同
  成员变量 有默认的初始化值
  局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。成员变量和局部变量的区别:
 在类中的位置不同
  成员变量 类中方法外
  局部变量 方法内或者方法声明上
 在内存中的位置不同
  成员变量 堆内存
  局部变量 栈内存
 生命周期不同
  成员变量 随着对象的存在而存在,随着对象的消失而消失
  局部变量 随着方法的调用而存在,随着方法的调用完毕而消失
 初始化值不同
  成员变量 有默认的初始化值
  局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。

 

变量的定义
 成员变量: 这个变量是否属于事物中的属性
 特点:变量的使用范问越小越好

方法的形式参数是类名的时候如何调用:

 形式参数:方法的参数列表中的参数
 实际参数:调用方法时,传递的参数

 基本数据类型:
  形式参数的改变 对 实际参数没有影响
 引用数据类型:
  形式参数的改变 对 实际参数   有影响
  
  class类型的参数,也属于引用数据类型

<span style="font-size:18px;">调用方式如下:
		
	class Student {
		public void study(){
			System.out.println("正在复习中");
		}
	}	
	
	class Test {
		public static void main(String[] args){
			//创建Test对象
			Test t = new Test();
			Student s = new Student();
			t.method( s );
		}
		
		public void method( Student s ){
		
			//this --> t对象
			s.study();
		}
	}</span>


 

构造方法

构造方法
 构造方法作用概述
  给对象的数据进行初始化
 构造方法格式:
  修饰符 类名(参数列表){...}
  
  方法名与类名相同
  没有返回值类型,连void都没有
  没有具体的返回值
  
 构造方法注意事项
  如果你不提供构造方法,系统会给出空参数的构造方法
  如果你提供了构造方法,系统将不再提供空参数的构造方法
  构造方法也是可以重载的

构造方法:用来构造类的实例(每一个类都默认有一个无参的构造方法,得使用new调用)

字段:类或对象所包含的数据,对类状态的一种描述;

方法:类或对象的特征或行为

作用:

给类中的字段进行初始化,可以用来创建对象。

特点:

方法名与类名相同

不用定义返回值类型

不需要写return语句

我的总结:

注意:

默认构造方法的特点。

多个构造方法是以重载的形式存在的。

构造方法的重载:(需要哪个就去适配哪个,调用哪个)

this([实参]);调用当前类的构造方法

注意: this([实参]);必须放在构造器的第一行;

 

对象的产生格式:

类名称  对象名 = new  类名称();

因为有(),所以是方法,实际上它就是构造方法,并且是非私有的构造方法。

如:CellPhone cp = new CellPhone();

Eg

<span style="font-size:18px;">class Person{
 
private String name;
 
private int age;
 
private int sal;
 

public void show(){
 
System.out.println("个人情况:"+name+age+sal);
 
}
 
 
 
public Person(String name) {
 
super();
 
this.name = name;
 
}
 
 
 
public Person(String name, int age) {
 
super();
 
this.name = name;
 
this.age = age;
 
}
 
 
 
public Person(String name, int age, int sal) {
 
super();
 
this.name = name;
 
this.age = age;
 
this.sal = sal;
 
}
 
}
</span>


成员方法的分类:
 返回值:
  有返回值的方法
  没有返回值的方法
 
 参数列表:
  空参数方法
  有参数方法成员方法的分类:
 返回值:
  有返回值的方法
  没有返回值的方法
 
 参数列表:
  空参数方法
  有参数方法成员方法的分类:
 返回值:
  有返回值的方法
  没有返回值的方法
 
 参数列表:
  空参数方法
  有参数方法成员方法的分类:
 返回值:
  有返回值的方法
  没有返回值的方法
 
 参数列表:
  空参数方法
  有参数方法

创建一个对象的步骤:
 Student s = new Student();
 
 加载Student.class文件进内存
 在栈内存为s开辟空间
 在堆内存为学生对象开辟空间
 对学生对象的成员变量进行默认初始化
 对学生对象的成员变量进行显示初始化
 通过构造方法对学生对象的成员变量赋值
 学生对象初始化完毕,把对象地址赋给s变量

 

静态关键字static

特点:

static关键字
 可以修饰成员变量和成员方法
 
 static关键字特点
  静态所修饰的成员,随着类的加载而加载,优先于对象存在
  静态所修饰的成员,会被所有对象共享
  可以通过类名调用
   类名.静态成员

使用注意:

静态方法只能访问静态成员

但是非静态成员可以访问静态成员;

静态方法中不可以使用thissuper关键字

主方法(main)是静态的(可以利用类名去调用静态的main方法,很正常!但是会陷入死循环,导致内存溢出,jvm自动停止!

public static void main(String[] agrs){}

可修饰字段,方法。

static修饰的成员表示它属于这个类共有,而不是属于该类的单个实例。

static 修饰的字段 ==类字段

static 修饰的方法 ==类方法

没使用static修饰的字段和方法,成员属于类的单个实例,

不属于类。

没有static修饰的字段==实例字段

没有static修饰的方法==实例方法

类和实例访问字段和方法的语法:

访问类成员: 类.字段    .方法

访问实例成员: 实例.字段    实例.方法

 

静态变量和成员变量的区别
 所属不同
  静态变量属于类,所以也称为为类变量
  成员变量属于对象,所以也称为实例变量(对象变量)
 内存中位置不同
  静态变量存储于方法区的静态区
  成员变量存储于堆内存
 内存出现时间不同
  静态变量随着类的加载而加载,随着类的消失而消失
  成员变量随着对象的创建而存在,随着对象的消失而消失
 调用不同
  静态变量可以通过类名调用,也可以通过对象调用
  成员变量只能通过对象名调用

 

 

 

我的总结:

static 修饰的字段和方法,既可以通过类调用,也可以使用实例调用;

static修饰的字段和方法,只能使用实例来调用(建议使用:类名来调用;其实在底层,对象调用类成员,也会转换类名调用)

static关键字不能与thissuper同时连用!

匿名对象

一个没有名字的对象创建了一个对象出来,没有赋给一个变量;

特点:

对方法或字段只进行一次调用时;

可作为实际参数进行传递;

只在堆里面开辟存储区域,

只能使用一次使用完就被销毁了;

何时使用?只拿来用一次!!

new Person();表示匿名对象,没有名字的对象

new Person().age = 17;//使用一次之后就被销毁了

 

匿名对象: 就是没有名字的对象
   是对象的一种简化表示形式

 匿名对象的两种使用情况:
  对象调用方法仅仅一次的时候
   new Student().study();

  作为实际参数传递
   t.method( new Student() );

this关键字

特点:this表示当前对象。

当前对象  ←→  当前正在调用实例成员的对象

换言之:谁调用了方法,谁就是当前对象。

什么时候使用this关键字呢?

方法间的相互调用;

this.字段;

构造器中相互调用,但是此时this([参数])必须写在构造方法第一行。

this不能用在static修饰的方法里和static修饰的代码块里;

 this关键字:
  this:代表所在类的对象引用
  记住:
   方法被哪个对象调用,this就代表那个对象
  什么时候使用this呢?
   局部变量隐藏成员变量
   

Eg:构造方法中的this.name = name;

封装

封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式
 好处:
  隐藏实现细节,提供公共的访问方式
  提高了代码的复用性
  提高安全性。
 封装原则:
  将不需要对外提供的内容都隐藏起来。
  把属性隐藏,提供公共方法对其访问

封装的两个含义:

1.把对象的状态和行为看成一个统一的整体,将二者存放在一个独立的模块中()

2."信息隐藏",把不需要让外界知道的信息隐藏起来,尽可能隐藏对象功能实现细节,字段;

封装机制在程序中的体现是:把描述对象的状态用字段表示,描述对象的行为用方法表示,把字段和方法定义在一个类中,并保证外界不能任意更改其内部的字段值,也不允许任意调动其内部的功能方法。

 

程序中的一种体现:通常将类中的成员变量私有化(private),通过对外提供方法(setXxx,getXxx,可对该变量(xxx)进行访问。

boolean 类型的变量没有getXX,只有isXX;

Eg

<span style="font-size:18px;">class Person1{
 
private String name;
 
private int age;
 
private int sal;
 

public String getName() {
 
return name;
 
}
 
 
 
public void setName(String name) {
 
this.name = name;
 
}
 
 
 
public int getAge() {
 
return age;
 
}
 
 
 
public void setAge(int age) {
 
this.age = age;
 
}
 
}
</span>

 

权限修饰关键字

 

private 类访问权限:本类内部可以访问,不能继承到子类

 private关键字:
  是一个权限修饰符。
  可以修饰成员(成员变量和成员方法)
  被private修饰的成员只在本类中才能访问

default 什么都不写,包访问权限:本类内部可以访问,同包其他类也可以访问,同包可继承;

protected 子类访问权限:本类内部可以访问,不同包的子类也可以访问,同包其他类也可以访问,能继承到子类;

public 公共访问权限:任何地方都可以访问,能继承到子类;

类的设计分析

分析思路:

根据要求写出类所包含的字段;

所有的字段都必须私有化;

封装之后的字段可通过settergetter设值和取得;

按需求可添加若干构造方法;

根据需求可添加相应的方法;

类中的所有方法都不要直接处理(输出打印),而是交给调用者去处理。

面向对象之继承

继承:
 概念:继承是从已有的类中派生出新的类,
   新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

继承的好处和弊端
 提高了代码的复用性
  多个类相同的成员可以放到同一个类中
  提高了代码的维护性
  如果功能的代码需要修改,修改一处即可
  让类与类之间产生了关系,是多态的前提
  
 其实这也是继承的一个弊端:类的耦合性很强

继承特点
 Java只支持单继承,不支持多继承
 Java支持多层继承(继承体系)
 
继承的注意事项:
 子类只能继承父类所有非私有的成员(成员方法和成员变量)
  其实这也体现了继承的另一个弊端:打破了封装性
 子类不能继承父类的构造方法,
  但是可以通过super(后面讲)关键字去访问父类构造方法
 不要为了部分功能而去继承
 
我们到底在什么时候使用继承呢?
 继承中类之间体现的是:”is a”的关系。
 例如: 梨是一种水果
 
this和super的区别
 this 代表本类对应的引用
 super代表父类存储空间的标识(可以理解为父类引用)
 
 用法(this和super均可如下使用)
 访问成员变量
  this.成员变量  super.成员变量
 访问构造方法(子父类的构造方法问题讲)
  this(…)  super(…)
 访问成员方法(子父类的成员方法问题讲)
  this.成员方法() super.成员方法()

继承中构造方法的注意事项:
 子类通过super去显示调用父类其他的带参的构造方法
  super(参数列表)
 子类通过this去调用本类的其他构造方法
  this(参数列表)
 一定要注意
  super(…)或者this(….)必须出现在第一条语句上
   否则,就会有父类数据的多次初始化

首先有反映一般事物特性的类,然后在此基础上反映出特殊事物的类;

也就是说:继承是一种从一般到特殊的关系;

特点:

1、提高了代码的复用性。

2、让类与类之间产生关系,有了这个继承关系才有了多态的特性。

3Java语言中只支持单继承(有别于C语言)。

因为多继承容易带来安全隐患(父类多了, 功能相同的话,就会出现调用不确定性吗,覆写一个方法,到底覆写的谁的?)。

ps:接口可以实现多继承

4Java支持多层继承,object是每个类的超类,实现树形结构。

我的总结:

继承是多态的前提。

对类而言,只支持单继承。

格式:

[修饰符] class SubClass extends SuperClass

按照这种关系,我们把SuperClass类称为父类或基类,把SubClass称为子类或派生类或拓展类;

我的总结:

java.lang.Object是所有类的父类,

Object要么是直接父类要么是间接父类。

Eg

学生属于人的一种特殊情况,此时我把人的共性写在Person类里面,为了让学生拥有这些共性(别的比如老师也可以有这些共性),然后我就让学生来拓展Person类。

我的总结:

子类与父类的关系:

子类拓展父类(子类是父类的一种特殊情况)

主要是以父类为基础,然后添加属于自己的字段和方法。

父类的私有成员子类不能继承到;父类的构造方法不能被继承;

Java只支持单继承,不支持多继承;//不然的话,比如show方法,继承了多个,不知道到底调用那一个。

一个类有且只有一个直接父类;

一个类没显示的继承其他的一个类的时候,默认的直接父类就是Object;

Student 的直接父类是Person,Object类也是Student类的父类,但是是间接父类;

一旦一个类显示的继承了其他的一个类的时候,此时默认的直接父类Object就会被取消;

Java里一个类只能有一个直接父类;java.lang.Object是所有类的父类,Object要么是直接父类要么是间接父类。

子类对象实例化过程

在继承操作中,对于子类对象的实例化:

子类对象在实例化之前必须首先调用父类中的构造方法之后再调用自身的构造方法。

子类访问父类和方法覆写

方法重写
 子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写。
 
 使用特点
  如果方法名不同,就调用对应的方法
  如果方法名相同,最终使用的是子类自己的
 
 方法重写的应用:
  当子类需要父类的功能,而功能主体子类有自己特有内容时,
  可以重写父类中的方法,
  这样,即沿袭了父类的功能,又定义了子类特有的内容
  
 方法重写的注意事项:
  1:父类中私有方法不能被重写
  2:子类重写父类方法时,访问权限不能更低
  3:父类静态方法,子类也必须通过静态方法进行重写。
   其实这个算不上方法重写,但是现象确实如此,
   至于为什么算不上方法重写,多态中我会讲解

子类不能直接访问父类的私有成员;

但是子类可以调用父类中的非私有方法来间接访问父类的私有成员。

Person类中有私有字段name,Student继承Person

new Sudent().name; ×

new Student().getName(); √

子类拓展父类(子类是父类的一种特殊情况)

主要是以父类为基础,然后添加属于自己的字段和方法。

方法覆写产生原因:

当父类中某个方法不适合于子类时,子类出现父类一模一样的方法.

判断必杀技:子类方法前加上@Override能编译通过,表明是方法的覆写。

调用被覆盖的父类方法:使用super.方法名(实参);

方法覆写时应遵循的原则(一同两小一大)

(一同):方法签名必须相同;

(两小):

子类方法的返回值类型比父类方法的返回值类型更小或相等

子类方法声明抛出的异常应比父类方法申明抛出的异常更小或相等;

(一大):子类方法的访问权限应比父类方法更大或相等;

子类需要覆写父类方法。

当父类的某个方法不适合于子类本身的特征行为时就当覆写父类中应当改变的方法。

final关键字
 final关键字是最终的意思  
  
  修饰类,类不能被继承
  修饰变量,变量就变成了常量,只能被赋值一次
  修饰方法,方法不能被重写

       

调用父类构造方法

表示父类对象的默认引用

如果子类要调用父类被覆盖的实例方法,可用super作为调用者调用父类被覆盖的实例方法。

使用super调用父类方法

使用super调用父类的构造方法

调用构造方法

本类中调用另一个重载构造方法用this(参数列表)

子类构造方法调用父类构造方法用super(参数列表)

子类调用父类的构造方法时:

super必须放在第一句

Java在执行子类的构造方法前会先调用父类无参的构造方法,其目的是为了对继承自父类的成员做初始化操作。

子类在创建对象的时候,默认调用父类的无参构造方法,要是子类构造方法中显示指定调用父类其他构造方法,就调用指定的父类构造方法,取消调用父类无参构造方法。

Eg

<span style="font-size:18px;">package reviewDemo;
 
 
 
class A{
 
String name;
 
A(){
 
System.out.println("父类默认隐式的构造方法!");
 
}
 

A(String name){
 
System.out.println("父类显式的构造方法!");
 
}
 
}
 
 
 
class B extends A{
 

B(){
 
super(null);
 
System.out.println("子类默认隐式的构造方法!");
 
}
 
}
 
 
 
public class Demo10 {
 
public static void main(String[] args) {
 
new B();
 
}
 
}
</span>


 

面向对象之多态

多态:指同一个实体同时具有多种形式

好比,你去面馆吃面,说我要吃面,那么;老板给我牛肉面,鸡蛋面等都可以,

这就是说""有多种形态,也就是说实体有多种形态;

编译时的类型由声明该变量时使用的类型决定,运行时的类型由实际赋给变量的对象决定。

如果编译时类型和运行时类型不同,就出现多态。

Eg

前提:Student  extends   Person:

 

<span style="font-size:18px;">Person p = new Person();
 
Student s = new Student();
 
Person p = new Student();//多态
</span>


 

引用关系:父类变量指向子类实例对象

实现多态的机制:

父类的引用变量可以指向子类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的真正实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。

多态的作用:

把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。

只修改方法的实现,不必修改方法的声明

继承是多态产生的前提条件;

分类:

编译时多态:方法重载

运行时多态:方法覆写

Eg

package test;

class Dog{

void eat(){

System.out.println("一般的狗吃一般的狗粮!");

}

}

class HashDogextends Dog{

void eat(){

System.out.println("哈士奇吃哈士奇的狗粮!");

}

}

class ZangAoDogextends Dog{

void eat(){

System.out.println("藏獒吃藏獒的狗粮!");

}

}

//定义一个动物园喂的方法

<span style="font-size:18px;">package test;
 
 
 
class Dog{
 
void eat(){
 
System.out.println("一般的狗吃一般的狗粮!");
 
}
 
}
 
 
 
class HashDog extends Dog{
 
void eat(){
 
System.out.println("哈士奇吃哈士奇的狗粮!");
 
}
 
}
 
 
 
class ZangAoDog extends Dog{
 
void eat(){
 
System.out.println("藏獒吃藏獒的狗粮!");
 
}
 
}
 
 
 
//定义一个动物园喂的方法
 
class Zoo{
 

void feed(Dog d){
 
d.eat();
 
}
 

}
 
 
 
public class Demo11 {
 
public static void main(String[] args) {
 

Dog hd = new HashDog();
 

Dog zd = new ZangAoDog();
 

Zoo z = new Zoo();
 
z.feed(hd);
 
z.feed(zd);
 
}
 
}
</span>


 

输出:

哈士奇吃哈士奇的狗粮!

藏獒吃藏獒的狗粮!

 

引用变量类型转换

向上转型(子类→父类):(自动完成)

父类名称 父类对象 = 子类实例;

向下转型(父类→子类):(强制完成)

子类名称 子类对象 = (子类名称)父类实例;

对象名   instanceof 

判断指定的变量名此时引用的真正类型是不是当前给出的类或子类;

我的总结:对象的类型和类必须有继承关系

Eg

<span style="font-size:18px;">class A extends B{}
 
 
 
B b = new A();
 
If(b instanceof A){ ...
 
}
</span>


 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值