JAVASE-DAY07

Posted winterriver

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVASE-DAY07相关的知识,希望对你有一定的参考价值。

DAY07

1.继承

1.1 继承(extends)实现类的扩展,子类是父类的扩展。

1.2 instanceof

二元运算符,左边是对象,右边是类;当左边是右边类或子类的对象时,返回true,否则返回false。

1.3 继承使用要点

  1. 父类也称作超类、基类、派生类等。

  2. Java中只有单继承,没有像c++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。

  3. Java中类没有多继承,接口有多继承。

  4. 子类继承父类,可以得到父类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(如,父类私有的属性和方法)。

  5. 如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。

1.4 方法重写

子类通过重写父类方法,可以用自身的行为替换父类的行为。方法的重写是实现多态的必要条件。

【要点】:

  1. “==”:方法名、形参列表相同。

  2. “≤”:返回值类型和声明异常类型,子类小于等于父类。

  3. “≥”:访问权限,子类大于等于父类。

1.5 Object类基本属性

Object类是所有Java类的根基类,也意味着所有的Java对象都拥有Object类的属性和方法。如果在类的生命中未使用extends关键字指明其父类,则默认继承Object类。

1.5.1 toString方法

Object类中定义有public String toString()方法,默认返回“类名+@+16进制的hashcode”。

public String toString() {
   return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

1.5.2 ==和equals方法

  • “==”代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。

  • Object的equals方法默认比较的是两个对象的hashcode,是同一个对象的引用时返回true,否则返回false。

  • JDK提供的一些类,如String、Date、包装类等,重写了Object的equals方法。调用这些类的equals方法,x.equals(y),当x和y所引用的对象是同一类对象且属性内容相等时(不一定是相同对象),返回true,否则返回false。

1.6 super关键字

super是直接弗雷对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性。

若子类构造方法的第一行代码没有显式的调用super(…)或this(…),那么Java默认都会调用super(),含义是调用父类的无参数构造方法。这里的super()可以省略。

1.6.1 属性/方法查找顺序

查找变量h:

  1. 查找当前类中有没有属性h;

  2. 依次上溯每个父类,查看每个父类中是否有h,直到Object;

  3. 如果没找到,则出现编译错误;

  4. 上述步骤,只要找到h变量,则该过程终止。

1.6.2 构造方法调用顺序

构造方法第一句总是:super(…)来调用父类对应的构造方法。

所以流程为:先向上追溯到Object,然后再依次向下执行类的初始化块和构造方法,直到当前子类为止。

静态初始化快调用顺序与构造方法调用顺序一致。

1.7 封装

1.7.1 概述

技术图片

程序设计要求“高内聚,低耦合”

高内聚是指类的内部数据操作细节自己完成,不允许外部干涉;

低耦合是指仅暴露少量的方法给外部使用,尽量方便外部调用。

编程中封装的优点:

  1. 提高代码的安全性。

  2. 提高代码的复用性。

  3. “高内聚”:封装细节,便于修改内部代码,提高可维护性。

  4. “低耦合”:简化外部调用,便于调用者使用,便于扩展和协作。

1.7.2 访问控制符

Java是使用“访问控制符”来控制哪些细节需要封装,哪些细节需要暴露的。

Java中4种“访问控制符”分别为private、default、protected、public,它们说明了面向对象的封装性,所以我们要利用它们尽可能的让访问权限降到最低,从而提高安全性。

技术图片

  1. private表示私有,只有自己类能访问。

  2. default表示没有修饰符修饰,只有同一个包的类能访问。

  3. protected表示可以被同一个包的类以及其他包中的子类访问。

  4. public表示可以被该项目的所有包中的所有类访问。

1.7.3 类的属性的处理

  1. 成员变量一般使用private访问权限。

  2. 提供相应的get/set方法来访问相关属性,这些方法通常是public修饰的,一提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头!)。

  3. 一些只用于本类的辅助性方法可以用private修饰,希望其它类调用的方法用public修饰。

1.8 多态

多态是指同一个方法调用,由于对象不同可能会有不同的行为。

  1. 多态是方法的多态,不是属性的多态(多态与属性无关)。

  2. 多态的存在要有3个必要条件:继承、方法重写、父类引用指向子类对象。

  3. 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。

1.9 对象的转型

父类引用指向子类对象,这个过程为向上转型,属于自动类型转换。

向上转型后的父类引用变量只能调用它编译类型的方法,不能调用它运行时类型的方法。

此时,我们就需要进行类型的强制转换,称之为向下转型。

向上转型:Fu f = new Zi();

向下转型:Zi z = (Zi) f;

1.10 final关键字

  1. 修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。

final int MAX_SPEED = 120;
  1. 修饰方法:该方法不可被子类重写。但是可以被重载!

final void study(){}
  1. 修饰类: 修饰的类不能被继承。比如:Math、String等。

final class A {}

1.11 抽象方法和抽象类

抽象方法

使用abstract修饰的方法,没有方法体,只有声明。定义的是一种“规范”,就是告诉子类必须要给抽象方法提供具体的实现。

抽象类

包含抽象方法的类就是抽象类。通过abstract方法定义规范,然后要求子类必须定义具体实现。通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用

抽象类的使用要点:

  1. 有抽象方法的类只能定义成抽象类

  2. 抽象类不能实例化,即不能用new来实例化抽象类。

  3. 抽象类可以包含属性、方法、构造方法。但是构造方法不能用来new实例,只能用来被子类调用。

  4. 抽象类只能用来被继承。

    5. 抽象方法必须被子类实现。

1.12 接口

1.12.1 概述

接口是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。

抽象类还提供了某些具体的实现,接口不提供任何实现,接口中所有的方法都是抽象方法。接口是完全面向规范的,规定了一批类具有的公共方法规范。

从接口的实现者角度看,接口定义了可以向外部提供的服务。

从接口的调用者角度看,接口定义了实现者能提供哪些服务。

接口是两个模块之间通信的标准,通信的规范。

接口和实现类不是父子关系,是实现规则的关系。

接口的本质

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须能干掉坏人;如果你是坏人,则必须欺负好人。

接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++、Java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

区别

  1. 普通类:具体实现

  2. 抽象类:具体实现,规范(抽象方法)

  3. 接口:规范!

1.12.2 如何定义与使用接口

声明格式

[访问修饰符] interface 接口名 [extends 父接口1, 父接口2…]{
   常量定义;
   方法定义;
}
  1. 访问修饰符:只能是public或默认。

  2. 接口名:和类名采用相同命名机制。

  3. extends:接口可以多继承。和类的继承类似,子接口扩展某个父类接口,将会获得父接口中所定义的一切。

  4. 常量:接口中的属性只能是常量,总是 public static final 修饰。不写也是。

  5. 方法:接口中的方法只能是:public abstract。

要点

  1. 子类通过implements来实现接口中的规范。

  2. 接口不能创建实例,但是可用于声明引用变量类型。

  3. 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。

  4. JDK1.7之前,接口中只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。

  5. JDK1.8后,接口中包含普通的静态方法。

1.12.4 面向接口编程

面向接口编程是面向对象编程的一部分。

接口就是规范,是项目中最稳定的东东。面向接口编程可以让我们把握住真正核心的东西,使实现复杂多变的需求成为可能。

通过面向接口编程,而不是面向实现类编程,可以大大降低程序模块间的耦合性,提高整个系统的可扩展性和可维护性。

1.13 内部类

1.13.1 概述

一般情况下,我们把类定义成独立的单元。有些情况下,我们把一个类放在另一个类的内部定义,成为内部类(innerclass)。

内部类可以用public、default、protected、private以及static修饰,而外部顶级类只能用public和default修饰。

内部类只是一个编译时的概念,一旦编译成功,就会成为两个完全不同的类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类。编译完成后会出现Outer.class和Outer$Inner.class两个类的字节码文件。所以内部类是相对独立的一种存在,其成员变量/方法名可以和外部类相同。

内部类的作用:

  1. 内部类提供了更好的封装。只能让外部类直接访问,不允许同一个包中的其他类直接访问。

  1. 内部类可以直接访问外部类的私有属性,内部类被当成其外部类的成员。 但外部类不能访问内部类的内部属性。

3. 接口只是解决了多重继承的部分问题,而内部类使得多重继承的解决方案变得更加完整。

内部类的使用场合:

  1. 由于内部类提供了更好的封装特性,并且可以很方便的访问外部类的属性。所以,在只为外部类提供服务的情况下可以优先考虑使用内部类。

  1. 使用内部类间接实现多继承:每个内部类都能独立地继承一个类或者实现某些接口,所以无论外部类是否已经继承了某个类或者实现了某些接口,对于内部类没有任何影响。

1.13.2 内部类的分类

在Java中内部类主要分为成员内部类(非静态内部类、静态内部类)、匿名内部类、局部内部类。

1. 成员内部类

(可以使用private、default、protected、public任意进行修饰。 类文件:外部类$内部类.class)

a) 非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)

i. 非静态内部类必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。

ii. 非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。

iii. 非静态内部类不能有静态方法、静态属性和静态初始化块。

iv. 外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例。

v. 成员变量访问要点:

1. 内部类里方法的局部变量:变量名。

2. 内部类属性:this.变量名。

3. 外部类属性:外部类名.this.变量名。

vi. 内部类的访问:

1. 外部类中定义内部类:

new Inner()

2. 外部类以外的地方使用非静态内部类:

Outer.Inner varname = new Outer().new Inner();

b) 静态内部类

i. 定义方式:

static class ClassName {
//类体
}

ii. 使用要点:

1. 当一个静态内部类对象存在,并不一定存在对应的外部类对象。 因此,静态内部类的实例方法不能直接访问外部类的实例方法。

2. 静态内部类看做外部类的一个静态成员。 因此,外部类的方法中可以通过:“静态内部类.名字”的方式访问静态内部类的静态成员,通过 new 静态内部类()访问静态内部类的实例。

匿名内部类

适合那种只需要使用一次的类。比如:键盘监听操作等等。

语法:

new 父类构造器(实参类表)实现接口() {
//匿名内部类类体!
}
?

注意

  1. 匿名内部类没有访问修饰符。

  1. 匿名内部类没有构造方法。因为它连名字都没有那又何来构造方法呢。

局部内部类

还有一种内部类,它是定义在方法内部的,作用域只限于本方法,称为局部内部类。

局部内部类的的使用主要是用来解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类。局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法中被使用,出了该方法就会失效。

局部内部类在实际开发中应用很少。

1.14 String类

1.14.1 基础

  1. String类又称作不可变字符序列。

  1. String位于java.lang包中,Java程序默认导入java.lang包下的所有类。

  1. Java字符串就是Unicode字符序列,例如字符串“Java”就是4个Unicode字符’J’、’a’、’v’、’a’组成的。

  1. Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义的类String,每个用双引号括起来的字符串都是String类的一个实例。

  2. Java允许使用符号"+"把两个字符串连接起来。

    • 符号"+"把两个字符串按给定的顺序连接在一起,并且是完全按照给定的形式。

    • 当"+"运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串然后再进行连接。

1.14.2 String类和常量池

1. 全局字符串常量池(String Pool)

全局字符串常量池中存放的内容是在类加载完成后存到String Pool中的,在每个VM中只有一份,存放的是字符串常量的引用值(在堆中生成字符串对象实例)。

2. class文件常量池(Class Constant Pool)

class常量池是在编译的时候每个class都有的,在编译阶段,存放的是常量(文本字符串、final常量等)和符号引用。

3. 运行时常量池(Runtime Constant Pool)

运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中,也就是说,每个class都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。

1.14.3 String类常用方法

技术图片

1.14.4 字符串相等的判断

  1. equals方法用来检测两个字符串内容是否相等。如果字符串s和t内容相等,则s.equals(t)返回true,否则返回false。

  1. 要测试两个字符串除了大小写区别外是否是相等的,需要使用equalsIgnoreCase方法。

  1. 判断字符串是否相等不要使用"=="。

以上是关于JAVASE-DAY07的主要内容,如果未能解决你的问题,请参考以下文章

JavaSE-day15

JAVASE-DAY14

JAVASE-DAY13

javaSE-day03(常用API一)

如何重构这个 Java 代码片段

使用androidx获取片段内的actionBar