黑马程序员(Java)----面向对象(中)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

3.1 继承的概述

    继承是面向对象的一个重要特征。当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继那个类即可。这时,多个类可以称为子类,单独的这个类称为父类或者超类。

继承的好处:

1、提高了代码的复用性

2、提高了代码的维护性

3、让类与类之间产生了关系,是多态的前提

继承的坏处:

类与类产生了关系,其实也是继承的一个弊端,因为类的耦合性增强了。

继承的用法:Java中使用extends关键字来表示子类继承父类,使用格式:class 子类名 extends 父类名。示例:

class Person {
	public void eat() {
		System.out.println("吃饭");
	}

	public void sleep() {
		System.out.println("睡觉");
	}
}

class Student extends Person {}

class Teacher extends Person {}

class ExtendsDemo {
	public static void main(String[] args) {
		Student s = new Student();
		s.eat();
		s.sleep();
		System.out.println("-------------");

		Teacher t = new Teacher();
		t.eat();
		t.sleep();
	}
}

运行结果:

3.2 继承的特点

1、Java只支持单继承,不支持多继承  。

2、Java支持多层继承(继承体系)。例如:class Son extends Father { }; class Father extends GrandFather { }

3.3 继承的注意事项

1、子类只能继承父类所有非私有的成员(成员方法和成员变量)

2、子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。

3、不要为了部分功能而去继承

3.4 继承中子父类成员的关系

3.4.1 super关键字

this和super的用法很相似,this代表本类对象的引用,super代表父类的内存空间的标识(可以理解为父类引用,可以操作父类的成员)。当本类的成员变量和局部变量同名用this来区分,当子父类中的成员变量同名用super来区分。

this调用的是当前类中的成员变量、构造方法和成员方法,super调用的是父类中的成员变量、构造方法和成员方法,并且调用构造方法时,该语句都必须是构造方法的第一句。

3.4.2 子父类中变量的特点

如果子类中出现非私有的同名成员变量时,子类要访问本类中的成员变量,用this。子类要访问父类中的同名成员变量,用super。this代表的是本类对象的引用。super代表的是父类对象的引用。示例:

class Father {
	public int num = 10;
}

class Son extends Father {
	public int num = 20;

	public void show() {
		int num = 30;
		System.out.println(num);
		System.out.println(this.num);
		System.out.println(super.num);
	}
}

class ExtendsDemo5 {
	public static void main(String[] args) {
		Son s = new Son();
		s.show();
	}
}

运行结果:

3.4.3 子父类中构造方法的特点

子类中所有的构造方法默认都会访问父类中空参数的构造方法,也就是说,在对子类对象进行初始化时,会先运行父类的构造方法。因为子类的构造函数默认第一行会有一条隐式的语句super(),super()会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super()。示例:

class Father {
	int age;

	public Father() {
		System.out.println("Father的无参构造方法");
	}

	public Father(String name) {
		System.out.println("Father的带参构造方法");
	}
}
class Son extends Father {
	public Son() {
		//super();  系统会默认在这个地方加上super();
		System.out.println("Son的无参构造方法");
	}

	public Son(String name) {
		//super();  系统会默认在这个地方加上super();
		System.out.println("Son的带参构造方法");
	}
}	

class ExtendsDemo6 {
	public static void main(String[] args) {
		Son s = new Son();
		System.out.println("------------");
		Son s2 = new Son("锤子");
	}
}

运行结果:

如果父类中没有无参的构造方法时,该怎么解决呢?

如果父类中没有无参的构造方法,可以通过使用super关键字去显示的调用父类的带参构造方法;也可以通过this关键字去调用本类的其他构造方法,但是必须保证子类中有一个构造方法访问了父类的构造方法。因为在子类对象进行初始化时,必须先初始化父类。示例:

class Father {
	public Father(String name) {
		System.out.println("Father的带参构造方法");
	}
}
class Son extends Father {
	public Son() {
		super("名字");
		System.out.println("Son的无参构造方法");
	}

	public Son(String name) {
		this();
		System.out.println("Son的带参构造方法---"+name);
	}
}
class ExtendsDemo7 {
	public static void main(String[] args) {
		Son s = new Son();
		System.out.println("----------------");
		Son ss = new Son("锤子");
	}
}

运行结果:

3.4.4 子父类中成员方法的特点

    建立一个子类的对象,该对象可以分别调用父类和子类中方法。当子父类中的方法同名时,子类的对象调用该方法时,会执行子类中的该方法,而不是父类中的该方法,这种情况叫方法的覆盖,也叫重写(override)。

1、怎么判断是否为重写(override)呢?

1)、具有父子关系的两个类。

2)、父类和子类各有一个函数,这另个函数的的定义(返回值类型、函数名、参数列表)完全相同。

class Phone {
	public void call(String name) {
		System.out.println("给"+name+"打电话");
	}
}

 class NewPhone extends Phone {
	public void call(String name) {
		//System.out.println("给"+name+"打电话");
		super.call(name);
		System.out.println("可以边打电话边看图片了");
	}
}

class ExtendsDemo9 {
	public static void main(String[] args) {
		NewPhone np = new NewPhone();
		np.call("锤子哥");
	}
}

运行结果:

2、方法重写(override)的注意事项

1)、父类中私有方法不能被重写,因为父类私有方法子类根本就无法继承

2)、子类重写父类方法时,访问权限不能低于父类该方法的权限,最好一致。

3)、父类静态方法,子类也必须通过静态方法进行重写

3、比较方法重载(overload)和重写(override)

1)、重载的两个函数存在于同一个类中;重写的两个函数存在于具有父子关系的两个类中。

2)、重载的函数名相同,参数列表(参数类型和参数数量)不同;重写的返回值类型、函数名和参数列表都相同。

示例:需求:创建一个动物的类,成员变量有name,age,color,构造方法包括有参和无参两种,成员方法有getXxx(),setXxx(),eat()。然后让Cat继承它,并复写eat()方法。

class Animal{
	private String name;
	private int age;
	private String color;

	public Animal(){}
	public Animal(String name,int age,String color){
		this.name = name;
		this.age = age;
		this.color = color;
	}

	public void eat(){
		System.out.println("别睡觉了,该吃饭了");
	}
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return name;
	}
	public void setAge(int age){
		this.age = age;
	}
	public int getAge(){
		return age;
	}
	public void setColor(String color){
		this.color = color;
	}
	public String getColor(){
		return color;
	}
}
class Cat extends Animal{
	public Cat(){}
	public Cat(String name,int age,String color){
		super(name,age,color);
	}
	public void eat(){
		System.out.println("我在吃东西");
	}
}
class ExtendsTest5{
	public static void main(String[] args){
		//方式1
		Cat c1 = new Cat();
		c1.setName("小花");
		c1.setAge(2);
		c1.setColor("黑白");
		System.out.println(c1.getName()+"---"+c1.getAge()+"---"+c1.getColor());
		c1.eat();
		//方式2
		Cat c2 = new Cat("小花",2,"黑白");
		System.out.println(c1.getName()+"---"+c1.getAge()+"---"+c1.getColor());
		c2.eat();
	}
}

运行结果:

3.5 子类实例化过程

以Zi z = new Fu(20)为例

1、把Zi.class文件加载到内存,由于Zi类继承Fu类,所以也将Fu.class文件加载到内存。

2、在栈内存为s开辟空间。

3、在堆内存为学生对象开辟空间。

4、给Zi类的成员变量age进行默认初始化(int类型的变量默认值为0)。

5、给Zi类的age成员变量在父类中进行显示初始化(int age = 1)。

6、通过父类的构造方法给age成员变量进行初始化(int age = 2)。

7、在子类中进行显示初始化(int age = 3)。

8、通过子类的构造方法给age进行初始化(int age = 4)。

9、对象构造完毕,把地址赋值给z变量。

验证:

class Fu{
	int age = 1;
	public Fu(){
		System.out.println(age);
		age = 2;
		System.out.println(age);
	}
}
class Zi extends Fu{
	int age = 3;
	public Zi(){
		System.out.println(age);
		age = 4;
		System.out.println(age);
	}
}
class Test{
	public static void main(String[] args){
		Zi z = new Zi();
	}
}

运行结果:

3.6 final关键字

1、final翻译成汉语就是“最终”的意思,可以修饰类、变量和函数。

被final修饰的类不可以被继承。

被final修饰的方法不可以被复写。

被final修饰的变量(成员变量和局部变量)是一个常量,且只能被赋值一次。

内部类只能访问被final修饰的局部变量。

2、常量的书写规范

所有字母大写。

如果由多个单词组成,单词间通过”_“连接。

3、final修饰局部变量

/*
    面试题:final修饰局部变量的问题
    基本类型:基本类型的值不能发生改变。
    引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。
*/
class Student {
	int age = 10;
}

class FinalTest {
	public static void main(String[] args) {
		//局部变量是基本数据类型
		int x = 10;
		x = 100;
		System.out.println(x);
		final int y = 10;
		//无法为最终变量y分配值
		//y = 100;
		System.out.println(y);
		System.out.println("--------------");

		//局部变量是引用数据类型
		Student s = new Student();
		System.out.println(s.age);
		s.age = 100;
		System.out.println(s.age);
		System.out.println("--------------");

		final Student ss = new Student();
		System.out.println(ss.age);
		ss.age = 100;//对象引用所指的堆内存中的值是可以改变的
		System.out.println(ss.age);

		//重新分配内存空间
		//无法为最终变量ss分配值
		//ss = new Student();
	}
}

运行结果:

结论:基本类型:基本类型的值不能发生改变。

引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 22:48:56

黑马程序员(Java)----面向对象(中)的相关文章

黑马程序员——JAVA面向对象学习总结

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- www.itheima.com 首先,面向对象是一种思想. 有一种面向过程的思想,面向对象就是基于面向过程的. 举个例子:把大象放进冰箱中. 面向过程: 用我们程序模拟 (java是纯面向对象语言) class Demo{ public static void main(String[] args){ /* 这几个动作相当于功能 既然是功能就用方法封装 */ //先打开冰箱门 open();

黑马程序员-Java面向对象编程学习总结

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- Java面向对象编程学习总结: 重要知识点总结如下: 1,抽象,封装,继承,多态是面向对象程序设计中得四个特点. 2,面向对象得软件开发大体分为:面向对象的分析,面向对象的设计,面向对象的实现. 可概括为如下过程:分析用户需求,从问题中抽

黑马程序员——JAVA面向对象的特性:封装,继承,多态

                                       - ----------android培训.java培训.java学习型技术博客.期待与您交流!------------  一.java面向对象的特性,封装.继承.多态         封装 封装是对象和类概念的主要特性. 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏. 继承 面向对象编程 (OOP) 语言的一个主要功能就是"继承".继承是

黑马程序员-Java面向对象上《二》

                         ------- android培训.java培训.期待与您交流! ---------- 1.面向对象的设计思想  面向过程:是以一个流程为单位,考虑它的实现方法,关心的是它的功能实现. 面向对象:是以具体事物为单位,考虑它的属性(特征)和动作(行为). 2.面向对象思考问题的方式 有哪些对象? 对象有什么特征和功能? 对象之间的关系? 3.类和对象 3.1,面向对象的编程思想:是力图使计算机语言中对事物的描述尽可能的与现实中的该事物的本来面目一致

黑马程序员-Java面向对象下《二》

                         ------- android培训.java培训.期待与您交流! ---------- 1.继承的概念 面向对象的特点之一,可以实现对类的复用.可以通过以下两种方法实现 a.合成/聚合关系(包含其他类):将一个类当作另一个类的属性. b.派生类:一个类继承另一个类,实现继承的类称为派生类,被继承类称为父类,基类,超类. 父类的成员方法和成员变量被子类继承,但是父类的构造方法没有被继承. 在Java中只支持单继承,和C++多继承不一样. 2.sup

黑马程序员——java语言中的关键字总结

关键字   1.定义:被java语言赋于了特殊含义的单词 2.用于定义基本数据类型的关键字: class  interface  float int long double byte short void boolean char  3.用于定义基本数据类型值的关键字:       true  false   null   4.用于定义流程控制的关键字: if else while for switch do default case continue return  break    5.用于

黑马程序员_Java面向对象思想

面向对象要把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法 . 1.人在黑板上画圆 对于这个设计,上面有Person, Blackborad , Circle三个对象 动词 : 画 因为画的动作的数据:坐标(x,y),半径(randius) 是Circle拥有的数据,所以 draw()方法应该属于Circle对象,而不是动作的发出者Person. 注意:[动作发出者往往会委托动作承受者 ] 2.司机紧急刹车 对于这个设计,上面有Driver, Car两个对象 动词 : 刹车 因为刹

黑马程序员-OC面向对象继承关系和组合关系笔记

继承关系是描述类和类之间的关系,两个类分别称为子类和父类,子类继承了父类,子类就拥有了父类的属性和方法: 继承的关系特点描述出来就是:** "是" **  (例如:学生类 是 人类) 组合关系描述的语句是:**** "拥有" ***  (例如:学生有成绩这个属性,而成绩属性本来就是一个成绩类的对象 ) 继承示例代码: #import <Foundation/Foundation.h> //Animal类的声明 @interface Animal : NS

黑马程序员–Java之多线程09

黑马程序员–Java之多线程09 一.线程和进程 在Java中,并发机制非常重要,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程.多线程就是指一个应用程序中有多条并发执行的线索,每条线索都被称作一个线程,它们会交替执行,彼此间可以进行通信.多线程是非常复杂的机制,在每个操作系统中的运行方式也存在差异,window操作系统是多任务操作系统,它以进程为单位.一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程,也就是正在执行的程序.系统

黑马程序员——java基础——异常

黑马程序员--java基础--异常 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 异常 就是不正常.程序在运行时出现的不正常情况.其实就是程序中出现的问题.这个问题按照面向对象思想进行描述,并封装成了对象.因为问题的产生有产生的原因.有问题的名称.有问题的描述等多个属性信息存在.当出现多属性信息最方便的方式就是将这些信息进行封装.异常就是java按照面向对象的思想将问题进行对象封装. 异常体系 --------java.lang.Thro