25内部类和常用类
Java基础——内部类和常用类
1 内部类
分类

定义
-
在一个类的内部再定义一个完整的类。
-
内部类也会生成class文件
代码:

编译生成的class文件

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

- 可为外部类提供必要的内部功能组件(身体 头)
1.1成员内部类
-
在类的内部定义,与实例变量、实例方法同级别的类。
-
外部类的-一个实例部分,创建内部类对象时,必须依赖外部类对象。(先创建外部类 才能创建内部类)
![image-20220407140512848]()
-
创建内部类时也可以添加关键字:默认的 私有的private 保护的 protected 公开的public
创建内部类

调用方法
- 先创建外部类
- 创建内部类:
外部类名字.new 内部类名字()

简化版 一步到位:

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

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


1.2 静态内部类
不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。(用法相当于一个外部类,功能上是给外部类提供一些功能)
只有静态内部类可以用static进行修饰,普通的类不可以用static进行修饰
调用外部类的属性时,不可以直接调用,将内外看成两个独立的类:
- 先创建一个外部类对象
- 然后再来调用外部类对象的属性
调用静态内部类的属性(包括静态属性,静态属性调用时注意需要采用 类名.静态属性名方式)可以直接调用
创建静态内部类

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

1.3 局部内部类
局部变量:定义在方法里
局部内部类:定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。前面不能加任何访问修饰符(public static protected default)
- 局部内部类可以访问外部类的属性,因为方法中就可以直接访问外部类的属性
- 局部内部类中不能包含静态的成员
- 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final.
创建局部内部类

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

一个小问题,怎样在局部内部类中访问局部变量:
dk1.7要求,变量必须是常量final;jdk1.8自动在外部局部变量前添加final,意味着后面不能对这个常量进行修改
因为如果不是final类型,运行完这个变量就消失了,但是内部类还一直调用这个属性,此时调用一个为空的属性程序要报错,所以要加final
相当于
1.4 匿名内部类
- 相当于创建了一个局部内部类

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

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

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

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

运行结果:

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

结果:(地址@哈希值)

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


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

结果:

equals()方法覆盖比较两个对象的内容是否相同,步骤:
重写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()方法

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

栈里面的数据放到堆里面,引用类型,就有一些方法可以使用
4.3 类型转换与装箱、拆箱
- 类型转换:基本数据类型(栈) 与 包装类型(堆)之间的转换
8种包装类提供不同类型间的转换方式:
- Number父类中提供的6个共性方法
- valueOf()静态方法

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

- Integer(为例)装箱


代码:
JDK1.5之前

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

-
parseXXX()静态方法:实现字符串和基本类型的转换
- 基本类型转成字符串
![image-20220407204015158]()
进阶版 将n1按16进制给出
![image-20220407204123876]()
更多:
![image-20220407204335457]()
-
字符串转成基本类型,在用parse时切记不能字符串中不能含有除数字以外的其他东西
![image-20220407204534353]()
-
boolean字符串形式转成基本类型:"true"-->true 非"true"-->false
![image-20220407210044928]()
注意:需保证类型兼容,否则抛出NumberFormatException异常。
4.4 整数缓冲区
- Java预先创建了256个常用的整数包装类型对象。
- 在实际应用当中,对已创建的对象进行复用。

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

结果是true

结果是false
- 两个明明都是相同的格式为什么返回结果不同why????
对class文件进行反编译后,可以看到,在自动装箱时实际上是利用valueOf进行装箱

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

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

5 String类
5.1 基本定义
-
字符串是常量,创建之后不可改变。
-
字符串字面值存储在字符串池(方法区中)中,可以共享。
-
栈:基本类型 堆:对象 方法区
不可变性:重新给name赋值时,原有的值并没有消失,而是一直保存在字符串池中!
字符串常量的共享:又有一个新的变量指向“zhangsan”时,二者指向同一个“zhangsan”


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

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

5.2 常用方法

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

结果:

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

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

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

程序结果:-23
5.3 可变字符串
- StringBuffer: 可变长字符串,JDK1. 0提供,运行效率慢、线程安全。
- StringBuilder: 可变长字符串,JDK5. 0提供,运行效率快、线程不安全。(单线程可用)
与String区别,
(1)效率比String高(2)比String省内存(3)输出时可以利用toString变成字符串
StringBuffer常用方法(StringBuilder类似)
- append 追加

结果:

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

结果:

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

结果:

- delete(start,end) 删除

结果:

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

结果:

这里为什么不是0.1和1那?因为double类型存储时是一种近似的存储,看似是1可能在内存里是0.9999999
很多实际应用中需要精确运算,而double是近似值存储,不在符合要求,需要借助BlgDecimal。
- 位置: java. math包中。
- 作用:精确计算浮点数。.
- 创建方式: BigDecimal bd=new BigDecimal(“1.0");(一定要用字符串的构造方法)
- 计算:不能用运算符,此时调用它的方法进行计算,返回的依然是BigDecimal类

除法时,进行除法运算时,如果不能准确的计算出结果时需要指定保留的位数和取舍方式。
- 除法: divide (BigDecimal bd, int scal ARoundingMode mode)
- 参数scal:指定精确到小数点后几位。
- 参数mode:
- 指定小数部分的取舍模式,通常采用四舍五入的模式,
- 取值为BigDecimal. ROUND_ HALF_ UP。
7 Date类
- Date表示特定的瞬间,精确到毫秒。Date类中的大部分方法都已经被Calendar类中的方法所取代。
- 时间单位
- 1秒=1000毫秒
- 1毫秒=1000微秒
- 1微秒= 1000纳秒
构造方法


方法摘要


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

创建时,可以使用getInstance来创建Calendar对象
输出时,如果直接使用calendar.toString输出的结果不是我们想要的,我们可以采用上面的calendar.getTime().toLocalString()来进行输出
- 获取时间信息

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

- add修改方法
减1个小时

- 这个月的最大最小天

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

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

解析 把字符串转成日期

结果:

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

结果:

currentTimeMillis():

可以用来计时:

gc():
告诉垃圾回收器回收











浙公网安备 33010602011771号