25内部类和常用类

Java基础——内部类和常用类

1 内部类

分类

image-20220407135033342

定义

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

  • 内部类也会生成class文件

代码:

image-20220407134752259

编译生成的class文件

image-20220407134823566

  • 内部类可以直接访问外部类的私有成员,而不破坏封装

image-20220407135257631

  • 可为外部类提供必要的内部功能组件(身体 头)

1.1成员内部类

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

  • 外部类的-一个实例部分,创建内部类对象时,必须依赖外部类对象。(先创建外部类 才能创建内部类)

    image-20220407140512848

  • 创建内部类时也可以添加关键字:默认的 私有的private 保护的 protected 公开的public

创建内部类

image-20220407135856482

调用方法

  • 先创建外部类
  • 创建内部类:外部类名字.new 内部类名字()

image-20220407140352494

简化版 一步到位:

image-20220407140437345

  • 内外类中属性重名,不写前缀优先调用内部类属性,要想访问外部类时,必须采用Outer.this

image-20220407140747052

  • 成员内部类不能定义静态成员,但是可以定义静态常量

image-20220407141353496

image-20220407141315864

1.2 静态内部类

不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。(用法相当于一个外部类,功能上是给外部类提供一些功能)

只有静态内部类可以用static进行修饰,普通的类不可以用static进行修饰

调用外部类的属性时,不可以直接调用,将内外看成两个独立的类:

  • 先创建一个外部类对象
  • 然后再来调用外部类对象的属性

调用静态内部类的属性(包括静态属性,静态属性调用时注意需要采用 类名.静态属性名方式)可以直接调用

创建静态内部类

image-20220407142114627

调用

没写Outer没写括号只是表示一种包含关系

image-20220407142516443

1.3 局部内部类

局部变量:定义在方法里

局部内部类:定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。前面不能加任何访问修饰符(public static protected default)

  • 局部内部类可以访问外部类的属性,因为方法中就可以直接访问外部类的属性
  • 局部内部类中不能包含静态的成员
  • 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final.

创建局部内部类

image-20220407144424011

调用方法

首先要想调用class Inner必须在方法内部创建局部内对象

image-20220407144724641

其次调用

image-20220407150413176

一个小问题,怎样在局部内部类中访问局部变量:

  • dk1.7要求,变量必须是常量final;jdk1.8自动在外部局部变量前添加final,意味着后面不能对这个常量进行修改

  • 因为如果不是final类型,运行完这个变量就消失了,但是内部类还一直调用这个属性,此时调用一个为空的属性程序要报错,所以要加final

image-20220407150854422

相当于

image-20220407151108993

1.4 匿名内部类

  • 相当于创建了一个局部内部类

image-20220407153041371

他在编译时也会产生class文件 但这个文件的名字不是我们取得 而是系统自己生成的

image-20220407154847252

  • 没有类名的局部内部类(一切特征都与局部内部类相同)。
  • 必须继承一个父类或者实现一个接口。
  • 定义类、实现 类、创建对象的语法合并,只能创建一个该类的对象。
  • 优点:减少代码量。 缺点:可读性较差。

2 Object类

image-20220407154731830

3 Object类常用方法

3.1 getClass()方法

  • public final Class<?> getClass() {}
  • 返回引用中存储的实际对象类型(class类型)
  • 应用:通常用于判断两个引用中实际存储对象类型是否一致。

image-20220407155429985

3.2 hashCode() 方法

  • public int hashCode() {}
  • 返回该对象的哈希码值。
  • 哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数
    值。
  • 一般情况下相同对象返回相同哈希码

image-20220407155746928

运行结果:

image-20220407155804829

3.3 toString() 方法

  • public String toString() {}
  • 返回该对象的字符串表示(表现形式)。
  • 可以根据程序需求覆盖该方法(返回值较为复杂),如:展示对象各个属性值。

默认的toString()方法产生的结果

代码:

image-20220407160257491

结果:(地址@哈希值)

image-20220407160311176

重写toString()方法(根据需求,也可以利用快捷键自动生成)

image-20220407160605173

image-20220407160700751

3.4 equals()方法

  • public boolean equals (Object obj)
  • 默认实现为(this == obj),比较两个对象地址是否相同
  • 可进行覆盖,比较两个对象的内容是否相同

覆盖前:

image-20220407163718624

结果:

image-20220407163608894

equals()方法覆盖比较两个对象的内容是否相同,步骤:

image-20220407163905073

重写equals方法:

if (this==obj){
    return true;
}
if(obj==null){
    return false;
}
if(obj instanceof Student){
    Student s = (Student)obj;
    //字符串比较用equals,String类型重写了equals方法
    if(this.name.equals(s.getName())&&this.age==s.getAge()){
        return true;
    }else{
        return false;
    }
}

3.5 finalize()方法

image-20220407165105212

4 包装类

4.1 什么是包装类

  • 基本数据类型所对应的引用数据类型
  • Object可统一所有数据,包装类(引用类型)的默认值是null。

4.2 包装类对应

image-20220407181604962

栈里面的数据放到堆里面,引用类型,就有一些方法可以使用

4.3 类型转换与装箱、拆箱

  • 类型转换:基本数据类型(栈) 与 包装类型(堆)之间的转换

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

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

image-20220407202051549

number方法拆箱:引用类型转成基本类型

image-20220407202204228

  • Integer(为例)装箱

image-20220407202448828

image-20220407202516052

代码:

JDK1.5之前

image-20220407203132174

JDK1.5之后,提供自动装箱和拆箱

image-20220407203303598

  • parseXXX()静态方法:实现字符串和基本类型的转换

    • 基本类型转成字符串

    image-20220407204015158

    进阶版 将n1按16进制给出

    image-20220407204123876

    更多:

    image-20220407204335457

    • 字符串转成基本类型,在用parse时切记不能字符串中不能含有除数字以外的其他东西

      image-20220407204534353

    • boolean字符串形式转成基本类型:"true"-->true 非"true"-->false

    image-20220407210044928

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

4.4 整数缓冲区

  • Java预先创建了256个常用的整数包装类型对象。
  • 在实际应用当中,对已创建的对象进行复用。

image-20220408090503691

结果是False:因为integer是引用类型,里面包含的是堆中的地址,地址指向的才是栈中的100,所以对于输出的比较表达式,实际上比较的是内存地址,肯定不相等!

image-20220408090812049

结果是true

image-20220408090837596

结果是false

  • 两个明明都是相同的格式为什么返回结果不同why????

对class文件进行反编译后,可以看到,在自动装箱时实际上是利用valueOf进行装箱

image-20220408091151814

问题根源在valueOf我们查看valueof的源码

image-20220408091512280

如果在-128-127范围内,就在return IntegerCache.cache[i+(-IntegerCache.low)]中进行取值,cache数组在运行时就已经初始化好了,在内存上是这样的,当给100时,栈中的变量会都指向在堆中缓冲区中已经初始好的100,而当给200,return new Integer(i)在我们的堆中开辟一个空间

image-20220408091829211

5 String类

5.1 基本定义

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

  • 字符串字面值存储在字符串池(方法区中)中,可以共享。

  • 栈:基本类型 堆:对象 方法区

不可变性:重新给name赋值时,原有的值并没有消失,而是一直保存在字符串池中!

image-20220408094432658

image-20220408094332521

字符串常量的共享:又有一个新的变量指向“zhangsan”时,二者指向同一个“zhangsan”

image-20220408094815955

image-20220408094740901

**字符串创建方式 **

  • String s = "Hello" ;产生-一个对象,字符串池中存储。
  • String s = new String( “Hello" ); //产生两个对象,堆、池各存储一个。(此时栈里面存储的时堆里面的空间,真正运行时堆和池中的会合并,最终还是指向池中的)

image-20220408095531004

结果是false,在堆中new出来的对象不同

image-20220408095519020

5.2 常用方法

image-20220408101309576

  • 利用toCharArray转换为数组以后直接输出的话是输出的数组的位置,可以利用Arrays.toString方法进行转化为字符串后输出
  • 利用split

image-20220408101612586

结果:

image-20220408101651223

将空格和逗号拆分,可以用[ ,]进行拆分

image-20220408101809187

如果不小心多写了几个空格,可以在中括号后面加上加号表示多个空格进行分割

image-20220408101930616

  • equals 比较内容是否一样,忽略大小写进行比较equalsIgnoreCase
  • compareTo 比较字典表里面的位置

image-20220408102237591

程序结果:-23

5.3 可变字符串

  • StringBuffer: 可变长字符串,JDK1. 0提供,运行效率慢、线程安全。
  • StringBuilder: 可变长字符串,JDK5. 0提供,运行效率快、线程不安全。(单线程可用)

与String区别,

(1)效率比String高(2)比String省内存(3)输出时可以利用toString变成字符串

StringBuffer常用方法(StringBuilder类似)

  • append 追加

image-20220408102927047

结果:

image-20220408103257861

  • insert (偏移量,追加字符串) 添加

image-20220408103051615

结果:

image-20220408103218092

  • replace(start,end,str) 替换 遵循含头部不含尾的原则

image-20220408103436471

结果:

image-20220408103455016

  • delete(start,end) 删除

image-20220408103616363

结果:

image-20220408103640504

拓展:清空 delete(start,sb.length())

6 BigDecimal类

image-20220408105414332

结果:

image-20220408105429423

这里为什么不是0.1和1那?因为double类型存储时是一种近似的存储,看似是1可能在内存里是0.9999999

很多实际应用中需要精确运算,而double是近似值存储,不在符合要求,需要借助BlgDecimal。

  • 位置: java. math包中。
  • 作用:精确计算浮点数。.
  • 创建方式: BigDecimal bd=new BigDecimal(“1.0");(一定要用字符串的构造方法)
  • 计算:不能用运算符,此时调用它的方法进行计算,返回的依然是BigDecimal类

image-20220408111003932

除法时,进行除法运算时,如果不能准确的计算出结果时需要指定保留的位数和取舍方式。

  • 除法: divide (BigDecimal bd, int scal ARoundingMode mode)
  • 参数scal:指定精确到小数点后几位。
  • 参数mode:
    • 指定小数部分的取舍模式,通常采用四舍五入的模式,
    • 取值为BigDecimal. ROUND_ HALF_ UP。

7 Date类

  • Date表示特定的瞬间,精确到毫秒。Date类中的大部分方法都已经被Calendar类中的方法所取代。
  • 时间单位
    • 1秒=1000毫秒
    • 1毫秒=1000微秒
    • 1微秒= 1000纳秒

构造方法

image-20220408111526821

image-20220408111537590

方法摘要

image-20220408111634553

image-20220408111700317

image-20220408111713077

8 Calendar

  • Calendar提供了获取或设置各种日历字段的方法。
  • 构造方法
    • protected Calendar() :由于修饰符是protected, 所以无法直接创建该对象。
  • 其他方法

image-20220408112746621

  • image-20220408112953691

创建时,可以使用getInstance来创建Calendar对象

输出时,如果直接使用calendar.toString输出的结果不是我们想要的,我们可以采用上面的calendar.getTime().toLocalString()来进行输出

  • 获取时间信息

image-20220408114551869

ps:月从0-11 显示的时候可以加1显示

  • 修改时间

image-20220408114852802

  • add修改方法

减1个小时

image-20220408114957819

  • 这个月的最大最小天

image-20220408115118825

9 SimpleDateFormat

  • SimpleDateFormat是-一个以与语言环境有关的方式来格式化和解析日期的具体类。
  • 进行格式化(日期->文本str)、解析(文本->日期)。
  • 常用的时间模式字母

image-20220408115336747

格式化date 把日期转成字符串

image-20220408115638500

解析 把字符串转成日期

image-20220408115941417

结果:

image-20220408115957147

10 System类

  • System系统类,主要用于获取系统的属性数据和其他操作,构造方法私有的 不用创建对象。
  • image-20220408120131875

arraycopy():

image-20220408120640900

结果:

image-20220408120653799

currentTimeMillis():

image-20220408120908040

可以用来计时:

image-20220408120959558

gc():

告诉垃圾回收器回收

posted @ 2023-08-18 15:59  努力学技术的小豪  阅读(51)  评论(0)    收藏  举报