java——Day5

第十章

  理解为什么要进行封装?封装有什么好处?封装的代码怎么实现?

10.1 知识框架

在这里插入图片描述

10.2 封装的理解

  封装说明白点就是对封装的对象进行保护,尽可能的隐藏封装对象的具体实现细节,让外部只能够通过特定的方式方法来访问该封装对象。
  此外,封装过后就形成了独立实体,独立实体可以在不同的环境下使用,这样可以降低程序的耦合度,提高程序的扩展性,以及重用性和复用性。

10.2.1 不封装存在问题

  一般来说我们所说的封装对象就是实体类,比如下面这段代码,如果不封装就会造成程序的不安全:

public class MobilePhone{
	double voltage;
}
public class MobilePhoneTest{
	public static void main(String[] args){
		MobilePhone phone = new MobilePhone;
		phone.voltage = 100;
		System,out.println("手机电压 = " + phone.voltage);
	}
}

  以上程序未对手机类进行封装,其电压属性对外暴露,在外部程序中可以随意的对电压属性进行访问修改,导致了他的不安全,因为手机的正常电压在3~5伏,但是上面的程序将他设成了100,显然是要出问题的,虽然程序编译运行没有报错,但是实际情况中显然是不对的。

10.2.2怎么封装

  封装的第一步就是应该将应该隐藏的数据隐藏起来,起码在外部是无法随意访问这些数据的,这里隐藏属性我们用的是private修饰符,表示私有的,只能在本类中访问,比如下面程序:

public class MobilePhone{
	private double voltage;
}
public class MobilePhoneTest{
	public static void main(String[] args){
		MobilePhone phone = new MobilePhone;
		phone.voltage = 100;
		System,out.println("手机电压 = " + phone.voltage);
	}
}

  这样加入private属性之后,上面的main方法执行就会报错,因为从外部无法访问voltage属性。那么既然属性不能够直接访问,这些属性应该怎么执行赋值等操作呢?
  解决方法:我们通过在类中编写set和get方法,来给属性赋值并获得属性的值,set和get方法被称之为实例方法,这些方法不能够被关键字static修饰。注意,set方法是没有返回值的,所以返回值填void,而get方法的返回值类型和返回的属性的类型一致。
  在这里讲一下方法被static和不被static修饰有什么区别:
1、被static修饰的方法,是静态方法,调用的时候不需要创建实例对象也可以执行,调用方法是:类名.方法名(实参)
2、没有被static修饰的方法被称为实例方法,意思就是说,这些方法不能够通过类名直接调用,必须要通过实例化对象,用实例化对象的引用来调用才可以,调用方法:引用.方法名(实参)
3、被static修饰的方法除了可以直接通过类名来调用,还可以用实例化对象的引用来调用,调用方法是:引用.方法名(实参)
  总结:封装的两个手段
1、给需要隐藏的属性加上修饰符static,表示这个属性是私有的,只在这个类中可以访问。
2、给加了修饰符static的属性建立set和get方法,这样可以通过set方法给实例化的对象属性赋值,也可通过get方法访问实例对象的属性。

第十一章 this和static

  理解什么是this,this能用在哪里,this什么时候可以忽略,什么时候不能忽略,以及怎么通过构造方法调用当前类中的其他构造方法。掌握静态代码块的执行时机,变量什么时候声明为静态变量,什么时候声明为实例变量,方法什么时候声明为实例方法,什么时候声明为静态方法,以及静态方法中为何不能直接访问实例变量和实例方法。

11.1 知识框架

在这里插入图片描述

11.2 this

11.2.1 this是什么

  简单点来说,this指的就是当前的实例对象。
  this可以看做一个变量,他是一个引用,存储在JVM堆内存的对象内部,this这个引用保存了当前对象的内存地址指向自身,任何一个堆内存中的java对象都有一个this,所以说jack.name和this.name是一样的,都是访问的当前对象的那么属性
  this可以用在实例方法和构造方法中,因为这两种方法是必须实例化对象之后才能够调用的方法。只有有了对象this才有意义。this不可以用在含有static的方法中,因为static方法的调用可以没有对象,这样也不会有this了。

11.2.2 this使用在构造方法中

  this还有一种用法,使用在构造方法的第一行(只能出现在第一行,这是规定,记住就行),通过当前构造方法调用本类中的其他构造方法,目的是为了实现代码的复用,比如一下代码:

public class Date{
	private int year;
	private int month;
	private int day;
	public Date(){
		#System.out.println(".....") 这段代码加上的话程序会报错,因为this在构造方法中只能出现在第一行
		this(1970,1,1);
	}
	public Date(int year,int month,int day){
		this.year = year;
		this.month = month;
		this.day = day;
	}
	# set和get方法省略
}

11.3 static

11.3.1 静态变量

  java 中的变量包括:局部变量和成员变量,而成员变量又包括实例变量和静态变量,当成员变量使用了static关键字,那么这种成员变量就变成了了静态变量,没有static修饰的成员变量称为实例变量。实例变量是对象级别的,所以必须要创建对象,通过对象来访问实例变量;静态变量是类级别的,不需要创建对象,可以直接通过类名来访问。
  静态变量在类加载的时候存储在方法区中,不需要创建对象。当然,和静态方法一样,他也可以通过引用来访问,不过这这个静态属性和引用无关,实际运行过程中还是通过类去访问的。
  注:空引用去访问静态变量或者静态方法,是不会发生空指针异常的,但是大部分情况下,我们还是用类名去访问。

11.3.2 静态代码块

  静态代码块的格式如下:

{
	//静态代码块
	static{
		java语句;
	}
}

  静态代码块在类加载时执行,并执行一次,静态代码块实际上是java语言为程序员准备的一个特殊的时刻,这个时刻就是类加载时刻
  一个类中可以写多个静态代码块,并且静态代码块遵循自上而下的顺序执行。

第十二章 继承

  了解继承在java中有什么用,以及在代码上如何实现继承

12.1 知识框架

在这里插入图片描述

12.2 继承

  继承是面向对象三大特征之一,封装居于首位,封装之后,类就成了独立体,独立体A和独立体B之间可能存在继承关系,其实就是想生活中的父子关系,所以有继承关系的两个类被称为父类和子类
  其中子类继承了父类的行为和动作,也就是继承了父类的属性和方法,使得子类具有父类相同的行为,并且子类可以扩展父类中没有的属性和方法,具有自己的特性。
  继承机制的作用:在不同的类中也可能会有相同的属性或者动作,可以把这些属性和动作放在一个类里面,让其他类共享。所以可以定义一个通用类,使其扩展程序多的特定类。比如java中的Object类,他和所有类都有继承关系,默认继承。

12.2.1 如何继承(掌握)

  java中继承的语法格式:

class 子类名 extends 父类名{
	类体;
}

  继承的作用中除了可以让代码复用之外,还有非常重要的两个作用,那就是有了继承之后才会衍生出方法的覆盖和多态机制,其中方法的覆盖就是对父类的方法重写,多态机制在下一章介绍。

12.2.2 继承的相关特性

1、B类继承A类,则称A类为超类、父类、基类,B类则称为子类、派生类、扩展类。
2、java中的继承只支持单继承,不支持多继承,即不支持这样写:
  class A extends B,C{}
3、虽然java不支持多继承,但有的时候会产生间接继承的效果,即A继承B,但B又继承C,所以A间接的继承C,也会具有C中的属性和方法。
  class A extends B{}
  class B extends C{}
4、java中规定,子类继承父类,除了构造方法和被private修饰的数据不能继承之外,剩下的都可以继承。
5、java中的类没有显示的继承任何类,则默认继承Object类,Object类是java语言提供的根类,也就是说一个对象与生俱来就有Object类中所有的特征。
6、继承也存在一些缺点,继承的双方耦合度也会变得非常高,一旦父类被修改,那么子类也会收到影响。
  注:
关于子类继承父类,官方文档是这样写的:

12.2.3 Object类中的toString方法

  toString方法返回的是当前对象的字符串表示,,输出一个引用就是调用他的toString方法,所以子类中我们必须要重写toString方法,确保输出的是我么期望的结果,不重写的话输出的就是“类名@hashCode值”
  为了使返回值更有意义,所以常用的类都已经重写了toString方法,如String类、Date类。我们自己写的类也建议重写toString方法。

第十三章 方法覆盖和多态

  理解在什么情况下我们需要进行方法覆盖,掌握在满足什么条件的时候构成方法覆盖,什么是多态,代码怎么写,向上转型和向下转型都是什么,多态在开发中的作用。

13.1 知识框架

在这里插入图片描述

13.2 方法覆盖 Override

13.2.1 什么时候需要方法覆盖

  当从父类中继承过来的方法无法满足当前子类业务需求的时候,需要将父类中继承过来的方法进行覆盖。换句话说就是父类中继承过来的方法已经不够用了,子类有必要将这个方法重新写一遍,所以方法覆盖又被称之为方法重写

13.2.2 方法覆盖的条件以及注意事项。

  那么当程序具备哪些条件的时候,就能构成方法覆盖呢?
1、方法覆盖式发生在具有继承关系的父子类之间,这是首要条件
2、覆盖之后的方法与原方法具有相同的返回值类型、相同的方法名、相同的形式参数列表;
  另外,在使用方法覆盖的时候需要有哪些注意事项呢?
1、由于覆盖之后的方法与原方法一模一样,建议在开发的时候采用赋值粘贴的方式,然后在此基础上改方法体即可
2、私有的方法不能被继承,所以不能被覆盖
3、构造方法不能被继承,所以不能覆盖
4、覆盖后的方法不能比原方法拥有更低的访问权限,可以更高
5、覆盖之后的方法不能比原方法抛出更多的异常,可以相同或更少
6、方法覆盖只是和方法有关,和属性无关
7、静态方法不存在覆盖(不是静态方法不能覆盖,只是静态方法覆盖的意义不大,这和多态机制有关)

13.3 多态

13.3.1 多态的语法基础

  多态属于面向对象的三大特征之一,他的前提是封装成独立体,独立体之间存在继承关系,从而产生多态机制。
  在java中允许这两种方法的出现,一种是向上转型,一种是向下转型,向上转型指的是子类型转换为父类型,又被称为自动类型转换,向下转型是指父类型转换为子类型,又称为强制类型转换。无论是向上还是向下都必须要求两个类之间一定要有继承关系。请看下图:
在这里插入图片描述
下面看一个多态的例子:

public class Animal {
	public void move(){
		System.out.println("Animal move!");
	} 
}
public class Cat extends Animal{
//方法覆盖
	public void move(){
		System.out.println("走猫步!");
	}
//子类特有
	public void catchMouse(){
		System.out.println("抓老鼠!");
	} 
}
public class Bird extends Animal{
//方法覆盖
	public void move(){
		System.out.println("鸟儿在飞翔!");
	}
}
//子类特有
	public void sing(){
 		System.out.println("鸟儿在歌唱!");
public class Test02 {
	public static void main(String[] args) {
		Animal a1 = new Cat();
		a1.move();
		Animal a2 = new Bird();
		a2.move();
	} 
}

  以上的代码就实现了多态的机制,其实多态指的就是“同一行为作用在不同的对象上”会有不同的结果,java之所以有多态机制,是因为java允许一个父类型的引用指向一个子类型的对象,也就是上面的:Animal a1 = new Cat(),这属于向上转型,也称为自动类型转换,虽然a1是父类型的引用,但存的确实子类型的对象。
  下面来解释一下:Animal a1 = new Cat();a1.move()代码片段:
java程序包括编译和运行两个阶段,首先进过编译阶段,在编译阶段编译器只知道a1变量是Animal类型的,那么编译器就回去Animal.class文件中去找move方法,找到了就绑定在a1的引用上,这被称为“静态绑定”,这样编译就通过了;紧接着进入运行阶段,在运行的时候实际上堆内存中new的对象是Cat类型,所以在运行时会自动执行Cat类中的move方法,这被称为“动态绑定”。最终得到结果。
  下面我们来看一下这一段程序:

public class Test03 {
	public static void main(String[] args) {
		Animal a = new Cat();
		a.catchMouse();
	} 
}

  首先,说一下上面这段代码在编译阶段就会报错,那为什么呢?
通过上面我们知道,在编译阶段,首先编译器会认为a是Animal类型的,那么他就会去找Animal类型中的catchMouse()方法,可想而知,不存在这个方法,“方法与引用静态绑定失败”,当然会报错。那么怎么解决呢,这里就需要用在“向下转型”(强制类型转换):

Cat c = (Cat)a;
c.catchMouse();

13.3.2 ClassCastException异常

  下面我们来讲一下ClassCastException异常:类型转换异常,先看一个例子:

public class Test05 {
	public static void main(String[] args) {
		Animal a = new Bird();
		Cat c = (Cat)a;
	} 
}

  这种异常通常出现在向下转型的过程中,当类型不兼容的情况下进行转型的异常,就比如上面的例子,a引用中存储的时候Bird对象,但是在向下转型的过程中将a转型成Cat对象,和原本的Bird对象类型不兼容,就会出现上述异常。这里建议在进行向下转型的过程中进行判断,是否引用中存储的是我们想要转型的类型,这里使用运算符“instanceof”,语法是:
  (引用 instanceof 类型)
  instanceof运算符的结果是布尔类型,如果结果为true,比如 a instanceof Cat,表示a引用指向Cat类型的对象,这样上面的的代码可以改成:

public class Test05 {
	public static void main(String[] args) {
		Animal a = new Bird();
		if(a instanceof Cat){
			Cat c = (Cat)a;
			c.catchMouse();
			} 
		} 
}

  静态方法为什么不谈覆盖?因为多态是在对象的基础上所产生的,但是静态方法的调用与对象无关,所以也就是与多态无关,那么静态方法的覆盖也就没有意义。

第十四章 super

  掌握super都可以用在哪里?理解super在内存方面存储的位置。掌握怎么通过子类的构造方法调用父类的构造方法。super什么时候可以省略,什么时候不能省略。

14.1 知识框架

在这里插入图片描述

14.2 super

14.2.1 super概述

  super和this对比:
1、this:
  a、this是一个引用,保存内存地址指向自己。
  b、this出现在实例方法中,谁调用这个实例方法,this就代表谁,this代表当前正在执行这个动作的对象。
  c、this不能出现在静态方法中。
  d、this大部分情况下可以省略,在方法中区分实例变量和局部变量的时候不能省略。
  e、“this(实际参数列表)”出现在构造方法的第一行,通过当前的构造方法去调用本类中的其他构造方法。
2、super:
  a、super其实并不是一个引用,他只是一个关键字,super代表了当前对象中从父类继承过来的那部分特征this指向一个独立的对象,super并不是指向某个“独立”的对象。这样看,实际上this是包含super的,super就是把当前对象从父类中继承过来的东西,在内存方面用super做了标记。看下图中的例子:
在这里插入图片描述
  b、super和this都可以用在实例方法当中。
  c、super不能使用在静态方法中,因为super代表当前对象的父类型特征,静态方法中没有this,当然也不能有super。
  d、super也有当前用法:“super(实际参数列表)”,这种用法是通过当前的构造方法来调用父类中的构造方法。只允许出现在第一行。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值