9.12第三周总结笔记

第三周总结

第一天~第四天:三大特性(封装、继承、多态) 三个修饰符(abstract、static、final)、接口

第五天~第六天: String类型的扩充、常用类

第一天

封装

什么是封装

概念:尽可能隐藏对象的内部实现细节,控制对象的修改以及访问的权限

访问修饰符:private(将属性修饰为私有,仅本类可见)

##### 过滤有效数据

外界访问 不可直接访问私有属性 仅可访问公共方法

get/set方法是外界访问对象私有属性的唯一通道,方法内部可对数据进行检测和过滤

继承

生活中的"继承"是施方的一种赠与,受方的一种获得

将一方所拥有的东西给予另一方

往往二者之间具有继承关系(直系、亲属)

继承

语法:class 子类 extents 父类{}//定义子类时,显示继承父类

应用:产生继承关系后,子类可以使用父类中的属性和方法,也可定义子类独有的属性和方法

好处:既提高代码的复用性,又提高代码的可扩展性

继承的特点

java为单继承,一个类只由一个直接父类,但可以多级继承,属性和方法逐级叠加

不可继承
  • 构造方法:

    类中的构造方法,只负责创建本类对象,不可继承

  • private修饰的属性和方法:

    访问修饰符的一种,仅本类可见

  • 父子类不在同一个包package中,default修饰的属性和方法:

    访问修饰符的一种,仅同包可见

访问修饰符
本类同包非同包子类其他
private×××
default××
protected×
public
方法的覆盖

当父类提供的方法无法满足子类需求时,可在子类中定义和父类相同的方法进行覆盖(Override)

方法重写的规则:

方法名必须相同

方法参数列表必须相同(个数、类型、顺序)

方法的返回值必须相同或返回值类型的子类

方法的访问修饰符,只能比父类更宽,不能更严

  • 方法覆盖原则:

    方法名称、参数列表、返回值类型必须与父类相同

    访问修饰符可与父类相同或是比父类更宽泛

  • 方法覆盖的执行:

    子类覆盖父类方法后,调用时优先执行子类覆盖后的方法

super关键字

在子类中,可直接访问从父类继承到的属性和方法,但如果父子类的属性或方法存在重名(属性遮蔽、方法覆盖)时,需要加以区分,才可专项访问

super调用父类无参构造

super();表示调用父类无参构造方法,如果没有显示书写,隐式存在于子类构造方法的首行

super调用父类有参构造

super();表示调用父类无参构造方法

super(实参);表示调用父类有参构造方法

this与super

this或super使用在构造方法中时,都要求在首行

当子类构造中使用了this()或this(实参)

即不可再同时书写super()或super(实参)

会由this()指向的构造方法完成super()的调用

总结
  • super关键字的第一种用法

    在子类的方法中使用"super."的形式访问父类的属性和方法

    例如:super.父类属性或super.父类方法();

  • super关键字的第二种用法

    在子类的构造方法的首行,使用"super()“或"super(实参)”,调用父类构造方法

  • 注意

    如果子类构造方法中,没有显示定义super()或super(实参),则默认提供super()

    同一个子类构造方法中,super()、this()不可同时存在

多态

程序中的多态

概念:父类引用指向子类对象,从而产生多种形态

二者具有直接或间接的继承关系,父类引用可指向子类对象,即形成多态

父类引用仅可调用父类所声明的属性和方法,不可调用子类独有的属性和方法

多态中的方法覆盖

如果子类中覆盖了父类中的方法,以父类型引用调用此方法时,优先执行父类还是子类中的方法?

实际运行过程中,依旧遵循覆盖原则,如果子类覆盖了父类中的方法,则执行子类中覆盖后的方法,否则执行父类中的方法

多态的应用
  • 场景一

    使用父类作为方法形参实现多态,使方法参数的类型更为宽泛

  • 场景二

    使用父类作为方法返回值实现多态,使方法可以返回不同子类对象

向上转型(装箱)

父类引用中保存真实子类对象,称为向上转型(即多态核心概念)

注意:仅可调用Animal中所声明的属性和方法

向下转型(拆箱)

将父类引用中的真实子类对象强转回子类本身类型,称为向下转型

注意:只有转换回子类真实类型,才可调用子类独有的属性和方法

类型转换异常

java.lang.ClassCastException

向下转型时,如果父类引用的子类对象类型和目标类型不匹配,则会发生类型转换异常

instanceof关键字

向下转型前,应判断引用中的对象真实类型,保证类型转换的正确性

语法:引用类型 instanceof 类型//返回boolean类型结果

总结

多态的两种应用场景:

  • 使用父类作为方法形参,实现多态

    调用方法时,可传递的实参类型包括:本类型对象+其所有的子类对象

  • 使用父类作为方法返回值,实现多态

    调用方法后,可得到的结果类型包括:本类型对象+其所有的子类对象

多态的作用:

屏蔽子类间的差异

灵活、耦合度低

第二天~第三天

abstract

抽象类的作用

作用:

1、可被子类继承,提供共性属性和方法

2、可声明为引用,强制使用多态

经验:

抽象父类,可作为子类的组成部分,依附于子类对象存在,

父类共性+子类独有组成完整的子类对象

抽象方法

被abstract修饰的方法,称为抽象方法,只有方法声明,没有方法实现({}的部分没有)。意为不完整的方法,必须包含在抽象类中

产生继承关系后,子类必须覆盖父类中所有的抽象方法,否则子类还是抽象类

总结

abstract修饰类:不能new对象,但可以声明引用

abstract修饰方法:只要方法声明,没有方法实现。(需包含在抽象类中)

抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类

子类继承抽象类后,必须覆盖父类所有的抽象方法,否则子类还是抽象类

static

实例属性

实例属性是每个对象各自持有的独立空间(多份),对象单方面修改,不会影响其他对象

静态属性

静态属性是整个类共同持有的共享空间(一份),任何对象修改,都会影响其他对象

什么是静态

概念:

  • 静态(static)可以修饰属性和方法
  • 称为静态属性(类属性)、静态方法(类方法)
  • 静态成员是全类所有对象共享的成员
  • 在全类中只有一份,不因创建多个对象而产生多份
  • 不必创建对象,可直接通过类名访问
静态方法

已知静态方法:

  • Arrays.copyOf();
  • Arrays.sort();
  • Math.random();
  • Math.sqrt();
  • 均使用类名直接调用
静态的特点

静态方法允许直接访问静态成员

静态方法不能直接访问非静态成员

静态方法中不允许使用this或是super关键字

静态方法可以继承,不能重写、没有多态

类加载

JVM首次使用某个类时,需通过CLASSPATH查找该类的.calss文件

类对象是一种数据类型 保存类的信息 类对象类的描述信息

将.class文件对类的描述信息加载到内存中,进行保存

如:包名、类名、父类、属性、方法、构造方法

加载时机:

  • 创建对象
  • 创建子类对象
  • 访问静态属性
  • 调用静态方法、
  • Class.forName(“全限定名”);
静态代码块

类加载时,触发静态代码块的执行(仅一次)。执行地位:静态属性初始化之后。

作用:可为静态属性赋值,或必要的初始行为

注:方法只有被调用才会执行

初始化静态属性、读取配置文件

总结
  • static修饰的成员为静态成员,无需创建对象,可直接通过类名访问
  • 静态方法不能直接访问非静态方法
  • 静态方法中不能使用this或是super
  • 静态方法可以继承、不能重写、没有多态
  • 静态代码块在类加载时被执行,但只执行一次

final

什么是最终

概念:最后的、不可更改的

final可修饰的内容:

  • 类(最终类)
  • 方法(最终方法)
  • 变量(最终变量)
final类

final修饰类:此类不能被继承

String、Math、System均为final修饰的类、不能被继承

final修饰方法:此方法不能被覆盖

意为最终方法,不支持子类以覆盖的形式修改

final变量

final修饰变量:此变量值不能被改变(常量)

所有final修饰的变量只能赋值一次,值不允许改变

实例常量

实例常量不再提供默认值,必须手动赋予初始值。

赋值时机:显示初始化、动态代码块、构造方法

如果有多个构造方法,必须保证每个构造方法都会对常量进行赋值

注意:如果在构造方法中为实例常量赋值,必须保证所有构造方法都能对其正确赋值

静态常量

静态常量

静态常量不再提供默认值,必须手动赋予初始值。

赋值时机:显示初始化、静态代码块

对象常量

final修饰的基本类型:值不可变

final修饰的引用类型:地址不可变

总结
  • final修饰类:此类不能被继承

  • final修饰方法:此方法不能被覆盖

  • final修饰变量:此变量值不能被改变(无初始值、只允许赋值一次)

    局部常量:显示初始化

    实例常量:显示初始化、动态代码块、构造方法

    静态常量:显示初始化、静态代码块

    基本数据类型常量:值不可变

    引用数据类型常量:地址不可变

第四天

接口

接口的语法

接口相当于特殊的抽象类,定义的方式、组成部分与抽象类类似

使用interface关键字定义接口

只能定义:公开静态常量、公开抽象方法

没有构造方法,不能创建对象

与抽象类的异同

相同:

  • 可编译成字节码文件
  • 不能创建对象
  • 可作为引用类型
  • 具备Object类中所定义的方法

不同:

  • 所有属性都是公开静态常量,隐式使用public static final修饰
  • 所有方法都是公开抽象方法,隐式使用public abstract修饰
  • 没有构造方法、动态代码块、静态代码块
什么是接口

微观概念:接口是一种能力和约定

  • 接口的定义:代表了某种能力
  • 方法的定义:能力的具体要求

经验:Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力

接口支持多实现,可为类扩充多种能力

接口的规范

任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类

实现接口中的抽象方法时,访问修饰符必须是public

接口的引用

同父类一样,接口也可声明为引用,并指向实现类对象

注意:

仅可调用接口中所声明的方法,不可调用实现类中独有的方法

可强转回实现类本身类型,进行独有方法调用

接口的多态

多种不同类型的引用指向同一个对象时,表示看待对象的视角不同

不同引用所能看到的对象范围不同,只能调用自身类型中所声明的部分

不同引用类型,仅可调用本身类型中所声明的方法

常见关系

类与类:

  • 单继承
  • extends 父类名称

类与接口:

  • 多实现
  • implement 接口名称1,接口名称2,接口名称3

接口与接口:

  • 多继承
  • extends 父接口1,父接口2,父接口3
常量接口

将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口中统一管理,提高代码可读性

#### 什么是接口

宏观概念:接口是一种标准

回调原理

接口回调:先有接口的使用者,后有接口的实现者

接口的好处
  • 程序的耦合度降低
  • 更自然的使用多态
  • 设计与实现完全分离
  • 更容易搭建程序框架
  • 更容易更换具体实现
总结
  • 什么是接口

    微观:接口是一种能力和约定

    宏观:接口是一种标准

  • 接口与类的异同

    没有构造方法,仅可定义公开静态常量与公开抽象方法

  • 接口的应用

    Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力

  • 接口的规范

    任何类在实现接口时,必须实现接口中所有的抽象方法,否则此类为抽象类

    实现接口中的抽象方法时,访问修饰符必须是public

  • 什么是常量接口

    将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口中统一管理

  • 什么是接口回调

    先有接口的使用者,后有接口的实现者

第五天

面试题

1、字符串有常量池 所有字符串都会存储在堆里面的字符串常量池中

(JDK1.8 字符串常量池从原本方法区中迁徙到堆中)

2、面试题:String a=new String(“a”) 会创建几个对象

1~2个 因为有new关键字会在堆中创建一个空间

如果字符串常量池中没有"a"就会在常量池中再创建一个空间

如果已经有了就不再创建,所以创建的对象是1~2个

字符串的创建每次都会扫描字符串常量池,看是否有这个值的存在

如果没有就创建有就直接使用自己创建的字符串

在这里插入图片描述

字符串拼接符

String c = "a" + "b";
String b = "ab";
System.out.println(c==b);//true

Java中有常量优化机制

编译器将这个"a"+"b"作为常量表达式,在编译时进行优化,取表达式结果"ab”

这里没有创建新的对象,而是从JVM字符串常量池中获取之前已经存在的"ab"对象

因此c,b具有对同一个string对象的引用,两个引用相等,结果true。

等同于

String c = "ab";
String b = "ab"
System.out.println(c==b);//true
String a = "a";
a = a + "b";
String b = "ab";
System.out.println(a==b);//false

输出结果为:false

为什么结果为false呢?

由此可见常量优化只是针对常量,如果有变量的话就不能被优化

对.class文件进行反编译

String a = "a";
a = (new StringBuilder(String.valueOf(a))).append("b").toString();
String b = "ab";
System.out.println(b == a);

a=a+“b” 变成了 a = (new StringBuilder(String.valueOf(a))).append(“b”).toString(); 这个

+号拼接有个字符串变量,在编译的时候就会出现new StringBuilder();

内存地址经过堆的空间和直接在字符串常量池的内存地址不一样

我的理解:

因为String是一个不可变的字符序列

做了如下三步操作

2、先将String类型转换成StringBuilder类型可变字符序列

3、在StringBuilder后追加子串

4、调用toString转为String类型

过了一遍StringBuilder后 StringBuilder底层是一个默认长度为16的char数组

只要含有变量的连接(拼接) 都会采用append进行追加子串

有一个new StringBuilder的过程

网上解答:

a = a + “b”;这一句话,是在StringBuffer缓冲区中进行创建一个StringBuffer对象,将两者相加。

但是对a进行赋值时不能够直接将缓冲区的对象地址取来而是用toString方法变成另外的堆内存,

然后赋值给a,所以,a和b的地址值已经不同了,所以输出false。

第六天

内部类

内部类的分类

内部类分为:成员内部类、静态内部类、局部内部类、匿名内部类

什么是内部类

概念:在一个类的内部再定义一个完整的类

特点:

  • 编译之后可生成独立的字节码文件
  • 内部类可直接访问外部类的私有成员,而不破坏封装
  • 可为外部类提供必要的内部功能组件
成员内部类

在类的内部定义,与实力变量、实例方法同级别的类

外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象

  • Outer out = new Outer();
  • inner in = out.new Inner();

当外部类、内部类存在重名属性时,会优先访问内部类属性

成员内部类不能定义静态成员

静态内部类

不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员

只能直接访问外部类的静态成员(实例成员需实例化外部类对象)

  • Outer.Inner inner = new Outer.Inner();
  • Out.Inner.show();
局部内部类

定义在外部方法中,作用范围和创建对象范围仅限于当前方法

局部内部类访问外部类当前中的局部变量时,因无法保障变量的生命周期与自身相同,变量修饰为final

限制类的使用范围

匿名内部类

没有类型的局部内部类(一切特征都与局部内部类相同)

必须继承一个父类或者实现一个接口

定义类、实现类、创建对象的语法合并,只能创建一个对象

  • 优点:减少代码量
  • 缺点:可读性较差

Object类

超类、基类,所有类的直接或间接父类,位于继承树的最顶层

任何类,如果没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承

Object类中所定义的方法,是所有对象都具备的方法

Object类型可以存储任何对象:

  • 作为参数,可接收任何对象
  • 作为返回值,可返回任何对象
getClass()方法

public final Class<?> getClass(){}

返回引用中存储的实际对象类型

应用:通常用于判断两个引用中实际存储对象类型是否一致

hashCode()方法

public int hashCode(){}

返回该对象的十六进制的哈希码值

哈希算法根据对象的地址字符串数字计算出来的int类型的数值

哈希码并不唯一,可保证相同对象返回相同哈希码,尽量保证不同对象返回不同哈希码

toString()方法

public String toString(){}

返回该对象的字符串表示(表现形式)

可以根据程序需求覆盖该方法,如:展示对象各属性值

equals()方法

public boolean equals(Object obj){}

默认是实现为(this == obj),比较两个对象地址是否相同

可进行覆盖,比较两个对象的内容是否相同

equalse方法覆盖

1、比较两个引用是否指向同一个对象。

if(this == obj){
	return true;
}

2、判断obj是否为null。

if(obj == null ){
	return false;
}

3、判断两个引用指向的实际对象类型是否一致。

if(this.getClass() != obj.getClass()){
	return false;
}

4、强制类型转换。

Worker w = (Worker)obj

5、依次比较各个属性值是否相同。

if(this.name.equals(w.name) && this.age == w.age && this.salary == w.salary){    return true;}
finalize()方法

当对象被判定为垃圾对象时,由jvm自动调用此方法,用以标记垃圾对象,进入回收队列

垃圾对象:没有有效引用指向此类对象时,为垃圾对象

垃圾回收:由GC销毁垃圾对象,释放数据存储空间

自动回收机制:JVM的内容耗尽,一次性回收所有垃圾对象

手动回收机制:使用System.gc();通知JVM执行垃圾回收

包装类

基本数据类型所对应的引用数据类型

Object可统一所有数据,包装类的默认值是null

包装类对应
基本数据类型包装类型
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean
charCharacter
类型转换与装箱、拆箱

8中包装类提供不同类型间的转换方式:

  • Number父类中提供的6个共性方法
  • parseXXX()静态方法
  • valueOf()静态方法

注意:需保证类型兼容,否则抛出NumberFormatException异常

JDK5.0之后,自动装箱、拆箱。基本数据类型和包装类自动转换

#### 整数缓冲区

Java预先创建了256个常用的整数包装类型对象

在实际应用当中,对已创建的对象进行复用

String类

字符串是常量,创建后不可改变

字符串字面值存储在字符串池中,可以共享

String s = “Hello”;产生一个对象,字符串池中存储

String s = new String(“Hello”);//产生两个对象 堆、池各存储一个

常用方法

public char charAt(int index):根据下标获取字符

public boolean conatins(String str):判断当前字符串中是否包含str

public char[] toCharArray():将字符串转换成数值

public int indexOf(String str):查找str首次出现的下标,存在,则放回该下标;不存在,则返回-1

public int lastIndexOf(String str):查找字符串在当前字符串中最后一次出现的下标索引

public int length():返回字符串的长度

public String trim():去掉字符串前后的空格

public String toUpperCase():将小写转成大写

public boolean endWith(String str):判断字符串是否以str结尾

public String replace(char oldChar,char newChar):将旧字符串替换成新字符串

public String[] split(String str):根据str做拆分

可变字符串

StringBuffer:可变字符串,JDK1.0提供,运行效率慢、线程安全

StringBuilder:可变长字符串,JDK5.0提供,运行效率快、线程不安全

StringBuiler扩容机制:默认长度为16 满了之后 (原长度*2+2)(value << 1 +2);

BigDecimal

位置:java.math包中

作用:精确计算浮点数

创建方式:BigDecimal bd = new BigDecimal(“1.0”);

方式:

  • BigDecimal add(BigDecimal bd) 加
  • BigDecimal subtract(BigDecimal bd) 减
  • BigDecimal multiply(BigDecimal bd) 乘
  • BigDecimal divide(BigDecimal bd) 除

除法:BigDecimal(BigDecimal bd, int scal,RoundingMode mode)

参数scal:指定精确到小数点后几位

参数mode:

指定小数部分的取舍模式,通常采用四舍五入的模式,

取值为BigDecimal.ROUND_HALF_UP

Date

Date表示特定的瞬间,精确到毫秒

Date类中表示的大部分方法都已被Calendar类中的方法所取代

时间单位:

1秒=1000毫秒

1毫秒=1000微秒

1微秒=1000纳秒

Calender

Calender提供了获取或设置各自日历字段的方法

protected Calender构造方法位protected 修饰无法直接创建该对象

  • static Clalendar getInstance() 使用默认时区和区域获取日历
  • void set(int year,int month, int date, int hourofday,int minute, int second) 设置日历的年、月、日、时、分、秒
  • int get(int field) 返回给定日历字段的值。字段比如年、月、日等
  • void setTime(Date date) 用给定的Date设置此日历的时间 Date-Calender
  • Date getTime() 返回一个Date表示此日历的时间 Calender-Date
  • void add(int field,int amount) 按照日历的规则,给指定字段添加或减少时间量
  • long getTimelnMillies() 毫秒为单位返回该日历的时间值

SimpleDateFormat

SimpleDateFormats是以与语言环境有关的方式来格式化和解析日期的类

进行格式化(日期->文本)、解析(文本->日期)

常用的时间模式字母

字母日期或时间示例
y2021
M年中月份09
d月中天数12
H1天中小时数(0-23)22
m分钟16
s59
S毫秒367

System类

System系统类,主要用于获取系统的属性数据和其他操作

static void arraycopy() 复制数组

staticlong currentTimeMillis() 获取当前系统时间、返回的是毫秒值

static void gc() 建议JVM赶快启动垃圾回收器回收垃圾

static void exit(int status) 退出JVM,如果参数是0表示正常退出JVM非0表示异常退出JVM

总结

  • 内部类

    在一个类的内部再定义一个完整的类

    成员内部类、静态内部类、局部内部类、匿名内部类

  • Object类

    所有类的直接或间接父类、可存储任何对象

  • 包装类

    基本你数据类型所对应的引用数据类型,可以使Object统一所有数据

  • String类

    字符串常量,创建之后不可改变,字面值保存再字符串池中,可以共享

  • BigDecimal

    可精确计算浮点数

  • 时间相关类:Date、Calender、SimpleDateFormat、System

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值