15 Object类
- Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父 类。即所有类的对象都可以使用Object的引用进行接收
使用Object接收所有类的对象
class Person{}
class Student{}
public class Test {
public static void main(String[] args) {
function(new Person());
function(new Student());
}
public static void function(Object obj) {
System.out.println(obj);
}
}
Person@1b6d3586
Student@4554617c
15.1 toString
-
当你打印一个对象时,实际上是调用了该对象的 toString() 方法,以获取对象的字符串表示形式。默认情况下,Object 类中的 toString() 方法返回的是一个由类名 + ‘@’ + 对象的哈希码组成的字符串。
然而,通常情况下我们会覆盖(override)这个方法,以便返回更有意义的信息,比如对象的属性值。通过覆盖 toString() 方法,可以自定义对象的字符串表示形式,以便于输出、日志记录等操作。
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
15.2 equals
- 在Java中,进行比较时
- a.如果==左右两侧是基本类型变量,比较的是变量中值是否相同
- b.如果==左右两侧是引用类型变量,比较的是引用变量地址是否相同
- c.如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的:
class Person{
...
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false ;
}
if(this == obj) {
return true ;
}
if (!(obj instanceof Person)) {
return false ;
}
Person person = (Person) obj ;
return this.name.equals(person.name) && this.age==person.age ;
}
}
结论:比较对象中内容是否相同的时候,一定要重写equals方法。
15.3hashcode
- 我们认为两个名字相同,年龄相同的对象,将存储在同一个位置,如果不重写hashcode()方法,我们可以来看示例 代码:
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class TestDemo4 {
public static void main(String[] args) {
Person per1 = new Person("gaobo", 20) ;
Person per2 = new Person("gaobo", 20) ;
System.out.println(per1.hashCode());
System.out.println(per2.hashCode());
}
}
460141958
1163157884
======================================
注意事项:两个对象的hash值不一样。
像重写equals方法一样,我们也可以重写hashcode()方法。此时我们再来看看
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public class TestDemo4 {
public static void main(String[] args) {
Person per1 = new Person("gaobo", 20) ;
Person per2 = new Person("gaobo", 20) ;
System.out.println(per1.hashCode());
System.out.println(per2.hashCode());
}
}
460141958
460141958
结论:
1、hashcode方法用来确定对象在内存中存储的位置是否相同
2、事实上hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的
散列码,进而确定该对象在散列表中的位置。
16.String类
16.1字符串构造
public static void main(String[] args) {
// 使用常量串构造
String s1 = "hello bit";
System.out.println(s1);
// 直接newString对象
String s2 = new String("hello bit");
System.out.println(s1);
// 使用字符数组进行构造
char[] array = {'h','e','l','l','o','b','i','t'};
String s3 = new String(array);
System.out.println(s1);
}
========================================
String是引用类型,内部并不存储字符串be
16.2String对象的比较
-
. ==比较是否引用同一个对象
-
注意:对于内置类型,==比较的是变量中的值;对于引用类型==比较的是引用中的地址。
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 10;
System.out.println(a == b);
System.out.println(a == c);
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("world");
String s4 = s1;
System.out.println(s1 == s2);
System.out.println(s2 == s3);
System.out.println(s1 == s4);
}
-
boolean equals(Object anObject) 方法:按照字典序比较
String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照
如下规则进行比较,比如: s1.equals(s2
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
==============================
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("Hello");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
}
- nt compareTo(String s) 方法: 按照字典序进行比较
与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:
1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = new String("ac");
String s3 = new String("abc");
String s4 = new String("abcdef");
System.out.println(s1.compareTo(s2));
System.out.println(s1.compareTo(s3));
System.out.println(s1.compareTo(s4));
}
- int compareToIgnoreCase(String str) 方法:与compareTo方式相同,但是忽略大小写比较
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = new String("ac");
String s3 = new String("ABc");
String s4 = new String("abcdef");
System.out.println(s1.compareToIgnoreCase(s2));
System.out.println(s1.compareToIgnoreCase(s3));
System.out.println(s1.compareToIgnoreCase(s4));
}
16.3字符串查找
- 字符串查找也是字符串中非常常见的操作,String类提供的常用查找的方法:
方法 | 功能 |
---|
char charAt(int index) | 返回index位置上字符,如果index为负数或者越界,抛出 IndexOutOfBoundsException异常 |
int indexOf(int ch) | 返回ch第一次出现的位置,没有返回-1 |
int indexOf(int ch, int fromIndex) | 从fromIndex位置开始找ch第一次出现的位置,没有返回-1 |
int indexOf(String str) | 返回str第一次出现的位置,没有返回-1 |
int indexOf(String str, int fromIndex) | 从fromIndex位置开始找str第一次出现的位置,没有返回-1 |
int lastIndexOf(int ch) | 从后往前找,返回ch第一次出现的位置,没有返回-1 |
int lastIndexOf(int ch, int fromIndex) | 从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返 回-1 |
int lastIndexOf(String str) | 从后往前找,返回str第一次出现的位置,没有返回-1 |
int lastIndexOf(String str, int fromIndex) | 从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1 |
16.4转化
1. 数值和字符串转化
public static void main(String[] args) {
String s1 = String.valueOf(1234);
String s2 = String.valueOf(12.34);
String s3 = String.valueOf(true);
String s4 = String.valueOf(new Student("Hanmeimei", 18));
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
System.out.println("=================================");
int data1 = Integer.parseInt("1234");
double data2 = Double.parseDouble("12.34");
System.out.println(data1);
System.out.println(data2);
}
=======================================
2. 大小写转换
public static void main(String[] args) {
String s1 = "hello";
String s2 = "HELLO";
System.out.println(s1.toUpperCase());
System.out.println(s2.toLowerCase());
}
----------------------------------------
3. 字符串转数组
public static void main(String[] args) {
String s = "hello";
char[] ch = s.toCharArray();
for (int i = 0; i < ch.length; i++) {
System.out.print(ch[i]);
}
System.out.println();
String s2 = new String(ch);
System.out.println(s2);
}
======================================
4. 格式化
public static void main(String[] args) {
String s = String.format("%d-%d-%d", 2019, 9,14);
System.out.println(s);
}
16.5 字符串替换
方法 | 功能 |
---|
String replaceAll(String regex, String replacement) | 替换所有的指定内容 |
String replaceFirst(String regex, String replacement) | 替换收个内容 |
- 注意事项: 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串.
16.6字符串的拆分
- 可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。
方法 | 功能 |
---|
String[] split(String regex) | 将字符串全部拆分 |
String[] split(String regex, int limit) | 将字符串以指定的格式,拆分为limit组 |
实现字符串的拆分处理
String str = "hello world hello bit" ;
String[] result = str.split(" ") ; // 按照空格拆分
for(String s: result) {
System.out.println(s);
}
字符串的部分拆分
String str = "hello world hello bit" ;
String[] result = str.split(" ",2) ;
for(String s: result) {
System.out.println(s);
}
注意事项:
1. 字符"|","*","+"都得加上转义字符,前面加上 "\\" .
2. 而如果是 "\\" ,那么就得写成 "\\\\" .
3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.
16.7字符串截取
方法 | 功能 |
---|
String substring(int beginIndex) | 从指定索引截取到结尾 |
String substring(int beginIndex, int endIndex) | 截取部分内容 |
观察字符串截取
String str = "helloworld" ;
System.out.println(str.substring(5));
System.out.println(str.substring(0, 5))
注意事项:
1. 索引从0开始
2. 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标
16.8StringBuilder和StringBuffer
- 由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。
方法 | 功能 |
---|
StringBuff append(String str) | 在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量 |
char charAt(int index) | 获取index位置的字符 |
void ensureCapacity(int mininmumCapacity) | 扩容 |
void setCharAt(int index, char ch) | 将index位置的字符设置为ch |
int indexOf(String str) | 返回str第一次出现的位置 |
int indexOf(String str, int fromIndex) | 从fromIndex位置开始查找str第一次出现的位置 |
int lastIndexOf(String str) | 返回最后一次出现str的位置 |
int lastIndexOf(String str, int fromIndex) | 从fromIndex位置开始找str最后一次出现的位置 |
StringBuff insert(int offset, String str) | 在offset位置插入:八种基类类型 & String类型 & Object类型数据 |
StringBuffer deleteCharAt(int index) | 删除index位置字符 |
StringBuffer delete(int start, int end) | 删除[start, end)区间内的字符 |
StringBuffer replace(int start, int end, String str) | 将[start, end)位置的字符替换为str |
String substring(int start) | 从start开始一直到末尾的字符以String的方式返回 |
String substring(int start,int end) | 将[start, end)范围内的字符以String的方式返回 |
StringBuffer reverse() | 反转字符串 |
String toString() | 将所有字符按照String的方式返回 |
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("hello");
StringBuilder sb2 = sb1;
sb1.append(' ');
sb1.append("world");
sb1.append(123);
System.out.println(sb1);
System.out.println(sb1 == sb2);
System.out.println(sb1.charAt(0));
System.out.println(sb1.length());
System.out.println(sb1.capacity());
sb1.setCharAt(0, 'H');
sb1.insert(0, "Hello world!!!");
System.out.println(sb1);
System.out.println(sb1.indexOf("Hello"));
System.out.println(sb1.lastIndexOf("hello"));
sb1.deleteCharAt(0);
sb1.delete(0,5);
String str = sb1.substring(0, 5);
System.out.println(str);
sb1.reverse();
str = sb1.toString();
System.out.println(str);
}
从上述例子可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可
以修改。频繁修改字符串的情况考虑使用StringBuilder。
注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:
String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
StringBuilder变为String: 调用toString()方法。
==============================
1. String、StringBuffer、StringBuilder的区别
String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
StringBuffer与StringBuilder大部分功能是相似的
StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操
作
==========================================
给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1
class Solution {
public int firstUniqChar(String s) {
int[] count = new int[256];
for(int i = 0; i < s.length(); ++i){
count[s.charAt(i)]++;
}
for(int i = 0; i < s.length(); ++i){
if(1 == count[s.charAt(i)]){
return i;
}
}
return -1;
}
}
计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000。(注:字符串末尾不以空格为结尾)
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String s = sc.nextLine();
int len = s.substring(s.lastIndexOf(' ')+1, s.length()).length();
System.out.println(len);
}
sc.close();
}
}
如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
字母和数字都属于字母数字字符。
给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。
class Solution {
public static boolean isValidChar(char ch){
if((ch >= 'a' && ch <= 'z') ||
(ch >= '0' && ch <= '9')){
return true;
}
return false;
}
public boolean isPalindrome(String s) {
s = s.toLowerCase();
int left = 0, right = s.length()-1;
while(left < right){
while(left < right && !isValidChar(s.charAt(left))){
left++;
}
while(left < right && !isValidChar(s.charAt(right))){
right--;
}
if(s.charAt(left) != s.charAt(right)){
return false;
}else{
left++;
right--;
}
}
return true;
}
}