目录
Object
祖宗类, 最大的父类. 所有类都直接或间接继承自Object
作用为约束所有类的所有对象都必须拥有某些方法, 可以根据需求对其中的部分方法进行重写
java.lang.Object
常用方法
-
类对象 getClass(): 获取引用的实际对象类型
-
可以通过
==
比较两个引用的实际对象类型是否一致-
原理: 一个类类对象只有一个, 对象类型一致则类对象地址一定一致
-
==
: 基本类型比较值, 引用类型比较地址
-
//利用多态创建一个学生对象 Person p1 = new Student(); System.out.println(p1.getClass()); //利用多态创建一个工人对象 Person p2 = new Worker(); System.out.println(p1.getClass() == p2.getClass());//f //创建学生对象2 Student stu = new Student(); System.out.println(p1.getClass() == stu.getClass());//t
-
-
int hashCode(): 获取对象的哈希码值
-
重写原因: 该方法默认关注对象地址, 但是实际开发中, 某些场景下我们需要关注的是对象内容, 对象内容一致则哈希码值应该一致, 所以需要对其重写
-
重写规则: 将属性值转换为数字相加
-
基本类型:
-
整数: 直接相加
-
小数及long: 强转为int相加
-
boolean: 对true和false做三元转换(转换为数字)相加
-
-
引用类型:
-
类库中的引用类型: 直接调用
属性名.hashCode()
相加 -
自定义的引用类型: 先重写hashCode, 再调用
属性名.hashCode()
相加 -
引用类型必须赋值再进行方法调用, 否则会触发空指针异常
空指针异常: java.lang.NullPointerException
触发场景: 用null参与运算 | 参与判断 | 调用内容
解决方案: 非空判断
-
package com.by.entity; public class Student extends Person{ private String name; private int age; private double score; private boolean sex; private Address addr; //重写hashCode public int hashCode(){ return name.hashCode() + age + (int) score + (sex ? 1 : 0) + (addr == null ? 0 : addr.hashCode()); } //省略getter&setter&构造 }
package com.by.entity; public class Address { private String address; //重写hashCode public int hashCode(){ return address.hashCode(); } //省略getter&setter&构造 }
package com.by.test; import com.by.entity.Address; import com.by.entity.Person; import com.by.entity.Student; public class Test2 { public static void main(String[] args) { Student stu1 = new Student("zhangsan", 20, 99.5,false,new Address("郑州市")); Student stu2 = new Student("zhangsan", 20, 99.5,false,new Address("郑州市")); System.out.println(stu1.hashCode() == stu2.hashCode());//t } }
-
-
-
boolean equals(Object o): 判断当前对象与参数对象是否相等
-
重写原因: 该方法默认比较地址, 但是实际开发中某些场景需要关注比较的是内容, 所以需要重写
-
重写规则:
-
属性值比较:
-
基本类型:
this.属性名 == 强转后的参数引用名.属性名
-
引用类型:
this.属性名.equals(强转后的参数引用名.属性名)
-
类库中的引用类型: 直接调用 重写过了 比较的是值
-
自定义的引用类型: 先重写equals, 再调用
public boolean equals(Object o) { //自反性: 自己和自己比, 一定相同 if (this == o) { return true; } //空值判断&类型比较: 与null值比|实际对象类型不同,一定不同 if (o==null || this.getClass()!=o.getClass()){ return false; } //类型强转: 将参数类型强转为当前类型 当前类名 引用名 = (当前类名) o; //属性值比较 return 当前对象this和引用名属性值的比较结果; }
-
-
package com.by.entity; public class Student extends Person{ ... //重写equals public boolean equals(Object o) {//Object o=new Student(..); //自反性: 自己和自己比, 一定相同 if (this == o) { return true; } //空值判断&类型比较: 与null值比|实际对象类型不同,一定不同 if (o==null || this.getClass()!=o.getClass()){ return false; } //类型强转: 将参数类型强转为当前类型 Student stu = (Student) o; //属性值比较 return this.name.equals(stu.name) && this.age == stu.age && this.score == stu.score && this.sex == stu.sex && this.addr.equals(stu.addr); } }
package com.by.entity; public class Address { //... //重写equals public boolean equals(Object o) { //自反性 if (this == o) { return true; } //空值 & 类型比较 if (o == null || this.getClass() != o.getClass()) { return false; } //类型强转 Address a = (Address) o; //属性值比较 return this.address.equals(a.address); } }
package com.by.test; import com.by.entity.Address; import com.by.entity.Student; import com.by.entity.Worker; public class Test3 { public static void main(String[] args) { Student stu1 = new Student("zhangsan", 20, 99.9,false,new Address("郑州市")); Student stu2 = new Student("zhangsan", 20, 99.0,false,new Address("郑州市")); System.out.println(stu1.equals(stu2));//t /* System.out.println(stu1.equals(stu1));//t System.out.println(stu1.equals(null));//f System.out.println(stu1.equals(new Worker()));//f*/ } }
-
-
-
String toString(): 返回对象的详细信息
-
重写原因: 该方法默认获取对象的地址信息, 但是开发过程中更多查看或操作的是对象的属性信息, 所以需要重写
-
重写规则: 按照查看需求拼接字符串即可
-
当直接使用或在String的环境下使用引用名时, 会默认调用toString()方法
package com.by.entity; public class Student extends Person{ //... @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + ", sex=" + sex + ", addr=" + addr + '}'; } }
package com.by.test; import com.by.entity.Address; import com.by.entity.Student; public class Test4 { public static void main(String[] args) { //定义一个学生数组, 遍历查看所有学生信息 Student[] ss = {new Student("zhangsan", 20, 99.9, false, new Address("郑州市")), new Student("lisi", 22, 94.9, false, new Address("郑州市")), new Student("wangwu", 21, 92.9, false, new Address("郑州市"))}; for (int i = 0; i < ss.length; i++) { System.out.println(ss[i]); } } }
-
-
void finalize(): 销毁垃圾对象
-
只能被虚拟机调用
-
垃圾回收机制: 当虚拟机内存满到不足以支撑新对象的创建时, 会调用垃圾对象们的finalize方法对其进行销毁,以此来释放内存空间
-
垃圾对象的判断标准: 没有任何引用指向的对象(零引用机制)
-
包装类
将基本类型包装为引用类型, 保留数据限制的同时可以存放操作null值及引用类型中的方法
byte | short | int | long | float | double | char | boolean |
---|---|---|---|---|---|---|---|
Byte | Short | Integer | Long | Float | Double | Character | Boolean |
基本类型和包装类型
自动转换
JDK5.0后
-
自动封箱: 基本类型转包装类型
-
自动拆箱: 包装类型转基本类型
基本类型与包装类型之间无法实现自动类型转换
int n1 = 10; Integer i1 = n1;//封箱 int n2 = i1;//拆箱 // Double d = n1; 报错
基本类型与String
基转String
-
拼接双引号
String 引用名=基本类型+""; String 引用名=""+基本类型;
-
valueOf
String 引用名=String.valueOf(基本类型);
String转基
基本类型 变量名=基本类型对应包装类名.parseXxx(String类型); 注: Xxx对应的为基本类型名,首字母大写
-
字符串内容必须为基本类型能够接受的内容,否则会在执行时触发
java.lang.NumberFormatException
数据类型转换异常
int n1 = 10; //拼接双引号 String s1 = n1 + ""; String s2 = "" + n1; //valueOf String s3 = String.valueOf(n1); String str = "100"; int n = Integer.parseInt(str); String str2 = "abc"; //int n2 = Integer.parseInt(str2); java.lang.NumberFormatException
包装类型与String
包转String
-
拼接双引号
String 引用名=包装类型引用名+""; String 引用名=""+包装类型引用名;
-
toString
String 引用名=包装类型引用名.toString();
String转包
-
利用构造(高版本JDK中将会剔除)
包装类型 引用名=new 包装类名(String类型);
-
valueOf
包装类型 引用名=包装类名.valueOf(String类型);
-
字符串中的内容必须为包装类型能够接收的内容
Integer i1 = 100;//封箱 //拼接双引号 String s1 = i1 + ""; String s2 = "" + i1; //toString String s3 = i1.toString(); String str = "100"; //利用构造-Integer Integer in1 = new Integer(str); //valueOf Integer in2 = Integer.valueOf(str); String str2 = "abc"; // Integer in3 = Integer.valueOf(str2); 报错
整数缓冲区
官方认定, -128至127是最常用的256个整数, 为了避免包装类型重复开辟占用空间, 所以在方法区中创立了整数缓冲区存储着这256个数字, 当包装类型使用的数字在区间之内, 则直接使用缓冲区的内容, 不会单独开辟堆空间
引用类型==比较地址时优先使用堆地址
Integer i1 = 127; Integer i2 = 127; System.out.println(i1 == i2);//t Integer i3 = 200; Integer i4 = 200; System.out.println(i3 == i4);//f Integer i5 = new Integer(127); Integer i6 = new Integer(127); System.out.println(i5 == i6);//f System.out.println(i1 == i5);//f
String
特点
不受引用特征的影响(无论引用是否为final), 都是内存中的常量, 内存内容一旦创建,不可更改
通过创建新地址并转换地址的方式实现字符串内容的改变
String s1 = "abc"; String s2 = s1; System.out.println("前s1: "+s1);//abc System.out.println("前s2: "+s2);//abc s1 = "edf"; System.out.println("后s1: "+s1);//edf System.out.println("后s2: "+s2);//abc
串池
全称字符串常量池. 实际开发中,字符串是使用频率最高的数据类型, 并且对字符串的复用率也很高, 为了避免重复字符串反复使用时创建空间导致的空间浪费, 所以在方法区中设立了串池, 目的为节省空间
创建方式
-
双引号直接赋值 (更推荐)
String 引用名="值";
-
构造赋值
String 引用名=new Stirng("值");
区别
-
优先使用串池. 会先从串池中寻找对应内容的地址, 如果有则直接指向, 没有则先在串池中创建然后指向
-
会开辟堆空间, 从串池中寻找对应内容的地址, 如果有则直接存放, 没有则在串池中创建然后存放
String s1 = "abc"; String s2 = "abc"; System.out.println(s1.equals(s2));//t System.out.println(s1 == s2);//t String str1 = new String("edf"); String str2 = new String("edf"); System.out.println(str1 == str2);//f System.out.println(str1.equals(str2));//t String str3 = new String("abc"); System.out.println(s1 == str3);//f System.out.println(s1.equals(str3));//t
可变长字符串
长度可变的字符串, 对象内容,不可使用串池
-
StringBuffer: JDK1.0 线程安全,效率慢
-
StringBuilder: JDK5.0 线程不安全,效率高
使用
-
必须通过构造创建
-
所有对内容的操作都必须通过调用方法实现
StringBuilder sb=new StringBuilder("abc"); StringBuilder sb2 = sb; System.out.println("前:"+sb);//abc System.out.println("前:"+sb2);//abc sb.append("edf"); System.out.println("后:"+sb);//abcedf System.out.println("后:"+sb2);//abcedf //拼接26个小写字母 StringBuilder s = new StringBuilder(); for (char c = 97; c <= 122; c++) { //将当前字符追加到可变长字符串末尾 s.append(c); } System.out.println(s);
宏观看, 对字符串复用率要远远高于对字符串的更改频率, 所以可以使用串池的String是更推荐使用的
常用方法
String引用名.方法名(..)
-
char charAt(下标): 获取指定下标位置的字符
-
boolean contains("值"): 判断字符串中是否存在指定内容
-
boolean endsWith("值"): 判断字符串是否以指定内容结尾
-
boolean startsWith("值"): 判断字符串是否以指定内容开头
-
boolean equals("值"): 判断内容是否相同, 区分大小写
-
boolean equalsIgnoreCase("值"): 判断内容是否相同, 不区分大小写
-
byte[] getBytes(): 以byte数组的形式返回字符串的每个内容
-
char[] toCharArray(): 以char数组的形式返回字符串的每个内容
-
下标 indexOf("值"): 获取指定内容第一次出现的下标
-
下标 lastIndexOf("值"): 获取指定内容最后一次出现的下标
-
boolean isEmpty(): 判断字符串内容是否为空, 不能判比null值
-
int length(): 获取字符串长度
-
String replace("旧字符串","新字符串"): 将新字符串替换掉所有的旧字符串
-
String[] split("分隔符"): 根据分隔符对字符串进行分割, 返回分割后的数组, 不保留分割符
-
String substring(开始下标): 将字符串从开始下标截取至末尾
-
String substring(开始下标, 结束下标): 3
-
将字符串从开始下标截取至结束下标前一位
-
String toLowerCase(): 转全小写
-
String toUpperCase(): 转全大写
-
String trim(): 去除前后空格
String s = "hello"; //charAt System.out.println(s.charAt(0));//h System.out.println(s.charAt(3));//l //System.out.println(s.charAt(5)); java.lang.StringIndexOutOfBoundsException //contains System.out.println(s.contains("he"));//t System.out.println(s.contains("hello"));//t System.out.println(s.contains("elo"));//f //endsWith System.out.println(s.endsWith("o"));//t System.out.println(s.endsWith("hello"));//t System.out.println(s.endsWith("l"));//f //startsWith System.out.println(s.startsWith("h"));//t //equals System.out.println(s.equals("hello"));//t System.out.println(s.equals("heLLo"));//f //equalsIgnoreCase System.out.println(s.equalsIgnoreCase("HELLO"));//t //getBytes byte[] bs = "abcd".getBytes(); for (int i = 0; i < bs.length; i++) { System.out.print(bs[i]+" ");//97 98 99 100 } System.out.println(); //toCharArray char[] cs = "abcd".toCharArray(); for (int i = 0; i < cs.length; i++) { System.out.print(cs[i]+" ");//a b c d } System.out.println(); //indexOf System.out.println(s.indexOf("l"));//2 //lastIndexOf System.out.println(s.lastIndexOf("l"));//3 //isEmpty System.out.println(s.isEmpty());//f System.out.println("".isEmpty());//t System.out.println(" ".isEmpty());//f String str = null; // System.out.println(str.isEmpty()); java.lang.NullPointerException //length System.out.println(s.length());//5 //replace System.out.println(s.replace("l","k"));//hekko //split String[] ss = "a,b,c,d".split(","); for (int i = 0; i < ss.length; i++) { System.out.print(ss[i]+" "); } System.out.println(); //substring System.out.println(s.substring(1));//ello System.out.println(s.substring(1,4));//ell //toLowerCase System.out.println("ABCDabcd".toLowerCase());//abcdabcd //toUpperCase System.out.println("ABCDabcd".toUpperCase());//ABCDABCD //trim System.out.println(" a b c ".trim());//a b c