Object
- Object类是所有java类的"顶级父类"
- 每个类使用Object作为超类, 所有对象(包括数组)都实现这个类的方法
- 在不明确给出超类的情况下, java会自动把Object类作为要定义的超类
常用方法
toString()
: 用于返回对应对象的字符串表示
hashcode()
: 用于返回对象对应的哈希码值
equals()
: 用来判断两个"对象"之间的相等
Object常用方法测试
package cn.tedu.object;
import java.util.Objects;
/**本类用于测试父类Object*/
public class Object1 {
public static void main(String[] args) {
Student s = new Student("海绵宝宝", 3);
Student s2 = new Student("海绵宝宝", 3);
//测试toString方法
/*重写前: 打印的地址值
* 重写后: 对象的类型和属性值Student{name='海绵宝宝', age=3}*/
System.out.println(s);
System.out.println(s2);
//测试hashCode()
/*打印对象的哈希码值
* 本方法: 用于返回对象的哈希码值
* 力求不同对象返回不同的哈希码值*/
System.out.println(s.hashCode());
System.out.println(s.hashCode());
System.out.println(s2.hashCode());
System.out.println(s2.hashCode());
//本类用于测试equals()
/*本方法底层的判断逻辑是==比较, ==比较的是左右两边的地址值
* 而s与s2是引用类型Student的对象, 保存时两个不同的地址值
* 所以, 地址值不同, equals()返回false
* 重写后: 比较左右两边的内容*/
System.out.println(s.equals(s2));
}
}
class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//在Student类中添加重写的toString()
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
String
- String是一个封装char[]数组的对象,字符串不可变
- String str = “abc”; 等效于:char data[] = {‘a’, ‘b’, ‘c’};
创建String对象的方式
- 方式一:
String(char[] value)
分配一个新的 String,使其表示字符数组参数中当前包含的字符序列。 - 方式二:
String str = “abc”;
- 如果是第一次使用字符串,java会在字符串堆中常量池创建一个对象。
- 再次使用相同的内容时,会直接访问堆中常量池中存在的对象。
String常用方法
int hashCode()
返回此字符串的哈希码。boolean equals(Object anObject)
将此字符串与指定的对象比较,比较的是重写后的串的具体内容String toString()
返回此对象本身(它已经是一个字符串!)。int length()
返回此字符串的长度。String toUpperCase()
所有字符都转换为大写。String toLowerCase()
所有字符都转换为小写boolean startsWith(String prefix)
测试此字符串是否以指定的元素开头。boolean endsWith(String suffix)
测试此字符串是否以指定的字符串结束。char charAt(int index)
返回指定索引/下标处的 char 值/字符int indexOf(String str)
返回指定字符在此字符串中第一次出现处的索引。int lastIndexOf(String str)
返回指定字符在此字符串中最后一次出现处的索引。String concat(String str)
将指定字符串连接/拼接到此字符串的结尾,注意:不会改变原串String[] split(String regex)
根据给定元素来分隔此字符串。String trim()
返回去除首尾空格的字符串byte[] getBytes()
把字符串存储到一个新的 byte 数组中String substring(int beginIndex)
返回一个新子串,从指定下标处开始,包含指定下标String substring(int beginIndex, int endIndex)
返回一个新子串,从执定下标开始,到结束下标为止,但不包含结束下标static String valueOf(int i)
把int转成String
测试String类的使用
package cn.tedu.String;
/*本类用来测试String类的使用*/
public class TestString {
public static void main(String[] args) {
//1.创建String的方式一
/*1. 字符串类型,底层维护的是char数组, 存在堆中*/
char[] value = {'a', 'b', 'c'};
String s1 = new String(value); //触发 String(char[]) 的含参构造来创建对象
String s11 = new String(value);
//2.创建String对象的方式二
String s2 = "abc";
String s22 = "abc";
String s3 = "ccc";
//3.测试
System.out.println(s1 == s2); //false 一个在堆里,一个在堆中常量池
System.out.println(s1 == s11); //false 两个不同的对象,地址值不同
System.out.println(s2 == s22); //true 都在堆中常量池,并且指向同一个,地址值相同
System.out.println(s2 == s3); //false 都在堆中常量池,数据不同,地址值不同
/*Object类中equals()默认实现是通过 == 来比较的 : 在比较基本类型时: 类型+属性值 比较引用类型: 地址值
* 但是String类已经自己重写了继承自object中的equals()
* 重写后, 不再按照 == 比较, 而是比较两个字符串的具体内容
* 也就是说, 不论创建方式, 只要是串的内容一致, equals()就返回true*/
System.out.println(s1.equals(s2)); //true
System.out.println(s1.equals(s11)); //true
System.out.println(s1.equals(s3)); //false
}
}
测试String常用方法
package cn.tedu.String;
import java.util.Arrays;
/**本类用来测试String常用方法*/
public class TestString2 {
public static void main(String[] args) {
String s = "abc";
char[] value = {'a', 'b', 'c'};
String ss = new String(value);
System.out.println(s.charAt(1)); //b 获取指定下标的元素
System.out.println(s.concat("cxy")); //abccxy, 用来拼接字符串,不会改变原串
System.out.println(s);
String s2 = s.concat("ccc"); // 拼接效果交给s2来保存,改变原串
System.out.println(s2);
System.out.println(s.startsWith("a")); //判断是否以指定元素开头
System.out.println(s.endsWith("y")); //判断是否以指定元素结尾
System.out.println(s.indexOf("b")); //判断下标
ss = "abcbb";
System.out.println(ss.indexOf("b"));
System.out.println(ss.lastIndexOf("b")); //元素最后一次出现的索引
System.out.println(ss.length());
String s3 = "a b c d e f";
System.out.println(s3.split(" ")); //打印的是地址值
System.out.println(Arrays.toString(s3.split(" "))); //使用数组工具类toString打印
String[] s33 = s3.split(" ");
for (int i = 0; i < s33.length; i++) {
System.out.println(s33[i]);
}
System.out.println(ss.toUpperCase()); //转换成全大写
System.out.println(ss.toLowerCase()); //转换成全小写
String s4 = "abcdefgh";
System.out.println(s4.substring(3)); //从指定下标截取到最后,包含头部
System.out.println(s4.substring(1,5)); //从指定位置截取到指定位置, 含头不含尾
String s5 = " abcde ";
System.out.println(s5.trim()); //用来去除字符串两端的空格
System.out.println(String.valueOf(10)); //转int为String
System.out.println("20" + 10); //2010 字符串拼接
System.out.println(String.valueOf(10) + 10); //1010
}
}
StringBuilder和StringBuffer
- 封装了char[]数组
- 是可变的字符序列
- 提供了一组可以对字符内容修改的方法
- 常用append()来代替字符串做字符串连接”+”
- 内部字符数组默认初始容量是16:super(str.length() + 16);
- 如果大于16会尝试将扩容,新数组大小原来的变成2倍+2,容量如果还不够,直接扩充到需要的容量大小。int newCapacity = value.length * 2 + 2;
- StringBuffer 1.0出道线程安全,StringBuilder1.5出道线程不安全
常用方法
append()
用作字符串的拼接
测试字符串拼接
package cn.tedu.String;
/*本类用于字符串的拼接*/
public class TestString3 {
public static void main(String[] args) {
//需求: 将26个字母拼接一万次
String s = "abcdefghijklmnopqrstuvwxyz";
// method1(s); //使用方式一拼接字符串
method2(s); //使用方式二拼接字符串
}
//使用方式二拼接字符串
private static void method2(String s) {
//1.创建工具类对象
StringBuffer sb = new StringBuffer();
StringBuilder sb2 = new StringBuilder();
long l = System.currentTimeMillis();
//2.拼接一万次
for (int i = 0; i < 10000; i++) {
// sb.append(s);
sb2.append(s);
}
long l1 = System.currentTimeMillis();
System.out.println(sb2);
System.out.println(l1 - l);
}
//使用方法一完成字符串的拼接
private static void method1(String s) {
//1.创建变量用来保存拼接后的效果
String result = "";
//5.给程序添加计时的功能
//5.1.获取循环开始的系统当前时间
long t1 = System.currentTimeMillis();
//2.创建循环执行10000次
for (int i = 0; i < 10000; i++) {
//3.进行字符串的拼接
result = result + s;
}
//5.2.获取拼接之后的系统当前时间
long t2 = System.currentTimeMillis();
//4.打印
System.out.println(result);
//5.打印花费的时间
System.out.println(t2 - t1);
System.out.println(t2);
}
}
==和equals的区别
- 当使用= =比较时,如果相比较的两个变量是引用类型,那么比较的是两者的物理地址值(内存地址),如果相比较的两个变量都是数值类型,那么比较的是具体数值是否相等。
- 当使用equals()方法进行比较时,比较的结果实际上取决于equals()方法的具体实现
- 默认是比较两个对象的地址值, 可以通过重写此方法用来比较双方的属性值
- 重写此方法, 要同时重写hashCode方法
包装类
把基本类型进行包装,提供更加完善的功能。
基本类型是没有任何功能的,只是一个变量,记录值,而包装类可以有更加丰富的功能
与基本类型的对应关系
Number
数字包装类的抽象父类。
提供了各种获取值的方式。
Integer
- 创建对象
- 方式一:
new Integer(5);
- 方式二:
Integer.valueOf(5);
- 方式一:
- Integer类中包含256个Integer缓存对象,范围是 -128~127
- 使用valueOf()时,如果指定范围内的值,直接访问缓存对象不新建;如果指定范围外的值,直接新建对象。
- 常见方法
static int parseInt(String s)
将字符串参数作为有符号的十进制整数进行解析
Double
- 创建对象
new Double(3.14)
Double.valueOf(3.14)
//和 new 没有区别
- 常用方法
Double.parseDouble();
Integer和Double练习
package cn.tedu.Number;
public class TestNumber {
static Integer i0;
public static void main(String[] args) {
System.out.println(i0); //默认值为null
Integer i1 = new Integer(5);
Integer i11 = new Integer(5);
System.out.println(i1 == i11);
//方式二
/*Integer有一个高效的效果, 数据在:(-128~127)范围内,相同的数据只会存一次, 后续再存都是使用之前存过的数据*/
Integer i2 = Integer.valueOf(127);
Integer i3 = Integer.valueOf(127);
System.out.println(i1 == i2); //false
System.out.println(i2 == i3); //true
/*满足高效效果的3个条件: Integer valueOf() -128~127*/
Integer i4 = Integer.valueOf(300);
Integer i5 = Integer.valueOf(300);
System.out.println(i4 == i5); //false
/*只有Integer的valueOf创建方式,并且数据在-128~127才有高效效果
* Double是没有高效效果的*/
Double d1 = new Double(3.14);
Double d2 = Double.valueOf(3.14);
Double d3 = Double.valueOf(3.14);
System.out.println(d1 == d2); //false
System.out.println(d2 == d3); //false
/*原因: parseInt()作用是把String类型的数据转为int
* 所以"800"被转成了int类型数据800, 就可以参与运算了
* 2.4 相同*/
System.out.println(i1.parseInt("800") + 8); //808
System.out.println(d1.parseDouble("2.4") + 1); //3.4
}
}
自动装箱和自动拆箱
自动装箱:把 基本类型 包装成对应的 包装类型 的过程
Integer a = 5;
//a是引用类型,引用了包装对象的地址。- 编译器会完成对象的自动装箱:
Integer a = Integer.valueOf(5);
自动拆箱:从包装类型的值,自动变成 基本类型的值
int i = a
;//a现在是包装类型,没法给变量赋值,需要把5取出来。- 编译器会完成自动拆箱:
int i = a.intValue();
自动装箱和自动拆箱练习
package cn.tedu.Number;
/***本类用于测试自动装箱与自动拆箱*/
public class TestNumber2 {
Integer i1 = new Integer(127);
Integer i2 = Integer.valueOf(127);
/*自动装箱: 编译器会自动把基本类型int5包装成包装类型Integer
* 然后交给Integer类型的引用类型变量i3来保存
* 自动装箱底层发生的代码: Integer.valueOf(5)
* valueOf()的方向: int --> Integer*/
Integer i3 = 5; //不会报错, 这个现象就是自动装箱
/*自动拆箱: 编译器会自动把包装类型的I1拆掉"箱子", 变回基本类型的数据127
* 然后交给基本类型int的变量i4来保存
* 自动拆箱底层发生的代码: i1.intValue();
* intValue()的方向: Integer0 -> int*/
int i4 = i1; //自动拆箱
}
BigDecimal解决浮点数运算不精确的问题
package cn.tedu.Number;
import java.math.BigDecimal;
import java.util.Scanner;
/**用来解决浮点数运算不精确的问题*/
public class TestBigDecimal {
public static void main(String[] args) {
// f1(); //使用普通的四则运算计算浮点型
f2(); //使用BigDecimal来解决浮点数不精确
}
//BigDecimal
private static void f2() {
System.out.println("请输入两个小数:");
double a = new Scanner(System.in).nextDouble();
double b = new Scanner(System.in).nextDouble();
//创建工具类对象
/*1.最好不用使用double作为构造函数的参数, 不然还会不精确的现象, 有坑!
* 2.使用重载的构造函数: 参数为String的构造函数
* double转String 直接在后面拼接一个空串就可以了, double与""拼接后转为String类型*/
BigDecimal bd1 = new BigDecimal(a + "");
BigDecimal bd2 = new BigDecimal(b + "");
//使用对象运算
BigDecimal bd3; //用来保存结果
bd3 = bd1.add(bd2);
System.out.println("加法:" + bd3);
bd3 = bd1.subtract(bd2);
System.out.println("减法:" + bd3);
bd3 = bd1.multiply(bd2);
System.out.println("乘法:" + bd3);
//方案一: 除不尽时会报错
// bd3 = bd1.divide(bd2);
System.out.println("除法:" + bd3);
//方案二:
/*divide(m,n,o)--m 除哪个对象
* n 代表除不尽时保留的小数, o 代表舍入方式(四舍五入: BigDecimal.ROUND_HALF_UP)*/
bd3 = bd1.divide(bd2, 3, BigDecimal.ROUND_HALF_UP);
System.out.println("除法:" + bd3);
}
//四则运算
private static void f1() {
System.out.println("请输入两个小数:");
double a = new Scanner(System.in).nextDouble();
double b = new Scanner(System.in).nextDouble();
System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b);
System.out.println(a / b);
}
}