摘要:本篇文章主要讲解java常用类(补Array)
写在开头:
调用类方法:如果本身是类对象的话,直接调用即可。如果本身是基本类型,可以通过类来调用
1 | char A = 'a'; |
一、内部类
0、分类:
成员内部类
静态内部类
局部内部类
匿名内部类
1、概念:
在一个类的内部再定义一个完整的类
1 | class Body{ |
特点:
编译之后会生成独立的字节码文件
内部类可以直接访问外部类的私有成员,而不破坏封装
2、成员内部类(???)
在类的内部定义的,与属性、方法同级别的类
在自己内部用:
因为成员内部类的的地位和成员一样,所以如果是成员方法的话,可以直接调用。而如果是static方法的话,先创建外部类实例
??
拿出去用:
内部类作为外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象
1 | Outer outer = new Outer(); |
注:如果要在其他文件中创建内部类对象,必须显示地导入内部类
外部类与内部类的属性重名时,优先访问内部类属性
1 | //重名时,如果想访问外部属性,前面加上Outer.this. |
注:内部类不能包含静态变量,但可以包含静态常量
3、!静态内部类
静态内部类=静态(成员内部类)
不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。
静态内部类直接当外部类使用即可,注意创建的时候要导入
1 | public class StaticClass { |
注!只有内部类才可以static修饰,外部类不可
4、局部内部类
定义在外部类方法中,甚至可以定义在方法的某个条件中,作用范围和创建对象仅限于当前方法
局部内部类的生命周期与方法的局部变量生命周期不相同,所以要求变量为final
1 | public class LocalClass { |
5、!匿名内部类
匿名内部类=匿名的局部内部类(一切特征与局部内部类相同)
通常用于继承父类或者实现接口
只能实例化一次,减少代码量,增加阅读复杂度
1 | public interface USB { |
二、Object类
1、definition
是所有类的直接或间接超类。位于继承树的最顶层
Object类中所定义的方法,是所有对象(包括数组)都具备的方法(通常也不会去重写Object方法)
Object类型可以存储任何对象
作为参数:接收任何对象
作为返回值:可返回任何对象
hashCode()方法:返回内存地址
2、func
2.1 getClass方法
返回一个类class:即对象的实际类型
应用:通常用于判断两个引用中实际存储对象类型是否一致
1 | public class People {} |
2.2 hashCode方法
返回对象的哈希码值
哈希值:根据对象的地址或字符串或数字使用hash算法计算出来的int类型数值,不是内存地址!!
一般情况下相同对象返回相同哈希码,可以用哈希码来判断是不是相同对象
1 | System.out.println(s1.hashCode()); |
2.3 toString方法
返回对象的字符串表示(默认是)
可以根据程序需求重写方法
1 | System.out.println(s1.toString()); |
2.4 equals方法
判断当前对象和传入对象是否是同一个对象,注意不是比较对象属性是否相同,而是比较对象本身是否相同
equals方法可以重写,用来比较两个对象的内容是否相同
2.5 finalize()方法 (已弃用)
当对象被判断为垃圾对象时,由JVM自动调用,用以标记垃圾对象,进入回收队列
- 垃圾对象:没有有效引用指向此对象时,为垃圾对象
- 垃圾回收:由GC销毁垃圾对象,释放数据存储空间
- 自动回收:JVM内存耗尽时,一次性回收所有垃圾对象
- 手动回收:使用Ststem.gc();通知JVM回收
1 | public class Stu{ |
三、包装类
思想:八大基本类型没有方法,操作起来不方便,为此设计了对应的封装类
Object可统一所有数据(都可以用Object来接收)。包装类的默认值是null
一旦基本类型数据包装后放在对象中,存储位置就在堆中了!
Integer构造方法中传入字符串,可以构造对应的值
1、类型转换&装箱&拆箱
类型转换:引用类型转换为基本类型
装箱:基本类型转引用类型(构造方法,valueof)
拆箱:引用类型转基本类型(Number下的byteValue等)
1 | int num = 10; |
1.1、ParseXXX()静态方法
1 | //1、基本类型转成字符串 |
1 | //2、字符串转成基本类型 |
1 | //boolean转成boolean |
1.2、整数缓冲区
1 | //引入 |
如果 num 处于-128~127之间,直接从cache数组中取值赋给它,否则再新建一个integer对象赋给它
优点:节省内存消耗
四、String类
引:
字符串放在方法区中,但方法区不一定在堆中
三种情况:
1、 java7之前,方法区位于永久代(PermGen),永久代和堆相互隔离,永久代的大小在启动JVM时可以设置一个固定值,不可变;2、 java7中,字符串常量池从永久代移到堆中;
3、 java8中,取消永久代,方法区存放于元空间(Metaspace),元空间仍然与堆不相连
没人要的字符串就变成垃圾了
给字符串赋值时,会去字符串池里面找有无对应值,有就指,没有就新建。
String详细分析(存疑–→JVM)
1.1 String对象创建两种方式
1 | a) String str1 = "abcd"; |
1 | c) String str3 = new String("mmm"); |
第一种创建方式:
- 先在栈中创建一个str1变量
- 在字符串池(in方法区)中寻找有无指定的字符串“abcd”,发现没有,则在字符串池中创建一个,然后让str1指向该字符串
1 e) str1 = "efgh"注:如果给str1赋一个新值“efgh”,原字符串“abcd”不会被回收,而是在方法区新建一个字符串常量“efgh”,然后让str1重新指向之。
第二种
先在栈中创建str3变量
在字符串池中创建一个“mmm”,然后在堆中创建一个String对象,其内容也是“mmm”(实质上是指向字符串池中的字符串常量)
1
2>//str3和str4指向的堆地址是不同的
>//str3和str4堆内容是相同的(相同的地址)由此可知
1
2>str3==str4//false:比较的是堆内存地址
>str3.equals(str4)//true:比较的是实际内容另外
1
>str1==str2//true,因为都指向字符串常量值同一片地址
1.2 String常用方法
Arrays类要导入,String类不用导
1 | //1 length();返回字符串长度,空格算字符 |
1 | //4 toCharArray();将字符串转为数组 |
1 | //7 trim();去掉字符串前后的空格 |
1 | //10 replace(char oldChar, char newChar)将旧字符(串)替换成新字符(串) |
关于split的技巧
1
2
3 //[ ,.]表示遇到这三个字符都会分开,解决了只能用一个字符的问题,不能用字符串
//[ ,]+表示遇到多个空格或者多个逗号,也会分开
//""这种普通表示可以用字符串或者字符切
补充:
equalsIgnoreCases():忽视大小写比较
compare():从两个字符串首字符开始比较,返回第一个不相同字符的ascii差
A.compare(B):返回A-B
1
2
3
4a = "abc";
b = "abcdef";
//当一个字符串用完了还没出现不同字符,则返回长度差,a.compare(b)=-3
//当两个字符串完全相同时,返回0(每一位差都是0)replace和replaceAll是JAVA中常用的替换字符的方法,它们的区别是:
1.replace即可以支持字符的替换,也支持字符串的替换
2.replaceAll的参数是regex或者char,即基于规则表达式的替换,比如,可以通过replaceAll(“\d”, “*”)把一个字符串所有的数字字符都换成星号;相同点是都是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串。
如果只想替换第一次出现的,可以使用replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的时,只替换第一次出现的字符串;
另外,如果replaceAll()和replaceFirst()所用的参数据不是基于规则表达式的,则与replace()替换字符串的效果是一样的,即这两者也支持字符串的操作;
Exercise:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 public static void main(String[] args) {
//返回给定字符串的每个单词首字母大写后的结果
String str = "java is the best language in the world";
String[] strArr = str.split(" ");
for (int i = 0; i < strArr.length; i++) {
char first = strArr[i].charAt(0);
char upFirst = Character.toUpperCase(first);
String news = upFirst+strArr[i].substring(1);
strArr[i] = news;
}
String nn = " ";
for (String s : strArr) {
nn = nn.concat(s);
nn = nn.concat(" ");
}
nn=nn.trim();
System.out.println(nn);
}
1.3 可变字符串
String局限:
- 出现大量垃圾
- 效率低
StringBuffer:提前开辟缓冲区,线程安全,效率慢(快于String)
StringBuilder:提前开辟缓冲区,线程不安全,运行效率快
1 | //StringBuffer StringBuilder的操作 |
含头不含尾原则:StringBuffer(Builder)的含有首尾参数的方法,都遵循含头不含尾原则。
五、其他常用类
1、BigDecimal类
引入:double存在的问题
1
2
3
4
5
6
7
8 double d1=1.0;
double d2=0.9;
System.out.println(d1-d2);
//0.09999999999999998
double result = (1.4-0.5)/0.9;
System.out.println(result);
//0.9999999999999999double的结果是不准确,可以采取保留若干位小数来精确,但总体是不准确的。
1
2 double f = 0.012324;
f = new BigDecimal(f).setScale(2,RoundingMode.HALF_UP).doubleValue();
1.0、Intro
- 位置:java.math包中
- 作用:精确计算浮点数
1.1、用法
注意初始化的时候用字符串,因为1.0,0.9本身在计算机中还是不准确的
1 | //BigDecimal |
2、Date类
1 | //Date类来封装时间 |
3、Calendar类
Date类许多方法已经弃用,建议使用Calendar类
1 | public static void main(String[] args) { |
4、SimpleDateFormat类
DateFormat 和SimpleDateFormat 的区别
1.DateFormat 可以直接使用,但其本身是一个抽象类,可以根据Locate指定的区域得到对应的日期时间格式
2.SimpleDateFormat 类是DateFormat 类的子类,一般情况下来讲 DateFormat 类很少会直接使用。而都使用SimpleDateFormat 类完成。
1 | public static void main(String[] args) { |
模式:
y:年 M:月 d:天数 H:小时 m:分钟 s:秒 S毫秒
5、系统(System)类
System系统类,主要用于获取系统的属性数据和其他操作,构造方法私有(不能实例化对象)
System中方法都是静态的,直接用即可。
1 | public class Sys { |
注:注意用系统获取时间方法可以计算过程耗时即可