Java Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。
Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。
public class Test {
public static void main(String[] args) {
Person person = new Person();
//调用person对象的方法toString()
String s = person.toString();
//com.yls.demo1.Person@1b6d3586 这是对象在内存中的“地址”
System.out.println(s);
//com.yls.demo1.Person@1b6d3586
System.out.println(person);
//得出结论 输出语句中必须(默认)调用toString()方法
//无权更改,sun公司规定死的
//输出语句System.out.println(对象)调用对象的toString()
//System.out.println(对象)==System.out.println(对象.toString())
}
}
在实际开发中,一般重写父类的toString()方法,不用默认的对象地址表现形式,而是建立我们自己的字符串表现形式
public class Person {
/**
* 重写父类的方法toString
* 返回字符串
* @return
* 重写方法的目标:方法中,返回类中成员变量的值
*/
private String name;
private int age;
public Person(){}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString(){
return name +":" + age;
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("李四",25);
//调用person对象的方法toString()
String s = person.toString();
//李四:25
System.out.println(s);
//李四:25
System.out.println(person);
}
}
public boolean equals(Object obj) {
return (this == obj);
}
//this指调用者,obj指传入的Object对象参数
默认比较对象的内存地址
但是一般对象的地址没有可比性,所以我们需要重写我们的equals方法,建立我们对象自己的比较形式
举例如下:
@Override
public boolean equals(Object obj){
//健壮性判断1,如果obj的值为null,比较的另一个对象不存在
if (obj == null) {
return false;
}
//健壮性判断2,判断this和obj是不是一个对象,如果是就直接返回true
if(this == obj){
return true;
}
//这里涉及一个多态的问题,
//obj应该向下转型为Person才可以调用age
//同时需注意安全性判断
if (obj instanceof Person) {
Person p = (Person) obj;
return this.age == p.age;
}
//不是Person 没有可比性
return false;
}
Person person = new Person("李四",25);
Person person1 = new Person("王二", 25);
boolean b = person.equals(person1);
System.out.println(b); //true
java.lang.Object
java.lang.String
All Implemented Interfaces:
Serializable , CharSequence , Comparable < String >
继承Object类 ,实现三个接口,字符串对象是常量,一旦创建不能修改
程序中只要写" ",都是String类的对象
字符串的实现原理
字符串数据类型在Java中是不存在的,其实现原理是char[]数组表示的
“abc” 实际上是char[] ch = {’a’, ‘b’, ‘c’}来表示
JDK9版本之后,为了节约内存,char数组变为byte数组
JDK8及以前都是char数组
public final class String
implements java.io.Serializable, Comparable , CharSequence {
/** The value is used for character storage. */
private final char value[]; //成员变量char数组
......
数组前修饰符final,表示最终数组,一旦建立其地址就被锁死(常量)为了线程安全。
字符串常量的特性
public static void main(String[] args) {
String a = "abc";
String s = new String("abc"); //new对象新开一片堆,与a String对象中的数组地址不一样
System.out.println(a == s); //false
System.out.println("---------------");
/**
* s1保存的是String对象
* s2 = "hello" 和s1中的字符串在内存中的数组表现是一样的 ,JVM为了节约内存两者共用
* s1的地址赋值给s2
*/
String s1 = "hello";
String s2 = "hello";
System.out.println(s1==s2); //true
System.out.println("---------------");
/**
* s3 和 s4都是变量,变量在编译的时候,javac不确定变量的计算结果是什么
* 运行的时候jvm会为s3+s4的结果新开内存空间
*/
String s3 = "hhh";
String s4 = "ooo";
String s5 ="hhhooo";
System.out.println(s5 ==(s3+s4)); //false
System.out.println("---------------");
/**
* "hhh" "ooo" 是常量,值在编译期间就已经确定
* 运行时期不会建立新的内存空间
*/
System.out.println(s5==("hhh"+"ooo"));//true
}
字符串构造方法
String(byte[] bytes)
通过使用平台的默认字符集解码指定的字节数组来构造新的 String 。
String(byte[] bytes, int offset, int length)
字节数组转换为字符串,使用平台默认字符集,参数off代表数组开始,len代表转换的个数
String(byte[] bytes, String charsetName)
charsetName是你自己可以指定的编码表 比如在idea上指定GBK
GBK编码为了和英文区别都是负值的
2字节表示一个汉字
utf-8是3个字节表示一个汉字
public static void Byte2string(){
/**
* String(byte[] bytes)
* 通过使用平台的默认字符集解码指定的字节数组来构造新的 String
* wiodows 中文版 默认字符集是GBK ,idea启动时为jvm添加启动参数会把默认字符集改为UTF-8
*/
byte[] b ={97,98,99};
String s = new String(b);
System.out.println(s); //abc
//数组的一部分转换为字符串
//从索引1开始,两个字符
String s1 = new String(b,1,2);
System.out.println(s1);//bc
}
public static void main(String[] args) {
Byte2string();
}
只有byte数组是和编码表有关,其他都无关
String(char[] value)
将数组变为字符串
String(char[] value, int offset, int length)
数组转换为字符串,参数off代表数组开始,len代表转换的个数
public static void Char2string(){
//构造方法,数组转为字符串
char ch [] ={'a','b','c','q'};
String s = new String(ch);
System.out.println(s);//abcq
//数组转为字符串转一部分
String s1 = new String(ch, 1, 2);
System.out.println(s1);//bc
}
String类的判断方法
/**boolean equals(Object anObject)
* 字符串直接的比较
* String继承自Object,重写父类方法
*/
boolean b = "abcd".equalsIgnoreCase("ABCD");
boolean c = "abcd".equals("abcD");
boolean d = "Hello,world".startsWith("Hello");
boolean e = "world,Hello".endsWith("Hello");
boolean f = "Hello fine".contains("fi");
boolean ff = "Hello fine".contains("if");
System.out.println(b); //true
System.out.println(c); //false
System.out.println(d); //ture
System.out.println(e); //true
System.out.println(f); //true
System.out.println(ff); //false
sun重写的equals方法如下
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;
}
String 类的获取方法,返回值不一定
//int length()返回字符串长度,字符串中字符的个数
int length = "abcde".length();
System.out.println(length);// 5
//char charAt(int index) 返回指定索引上的单个字符
char chr = "hedfgg".charAt(3);
System.out.println(chr); //f
//int indexOf(String str)返回指定的字符串,在当前字符串中第一次出现的索引
int index = "hello word so smart".indexOf("s");
System.out.println(index);//11
//以s第一次出现为准
int index1 = "hello word so smart".indexOf("so");
System.out.println(index1);//11
//int lastindexOf(String str)返回指定的字符串,在当前字符串中最后一次出现的索引
int index2 = "hello word so smart".lastIndexOf(" ");
System.out.println(index2);//13
//String substring(int start,int end)截取字符串,参数表示开始和结束索引,其中截取包含开始索引,不包含结束索引
String str = "hello world"; //是锁死的字面量”hello world”
String str1 = str.substring(2,5); //如果不赋值的化仍然是原str ,需要赋值新的字符串
System.out.println(str1);//llo
System.out.println(str.substring(2,5));//llo
String类的比较大小方法
/**
* int compareTo(String anotherString) 按字典顺序(自然顺序)比较两个字符串
*/
String str1 = "abcdef";
String str2 = "abdefg";
String str3 = "abcdef";
String str4 = "abcdeg";
/**
* 返回值是int
* 返回值为负,调用者小
* 返回值为正,调用者大
* 返回值为0,一样大
*/
int i = str1.compareTo(str2);
int j = str1.compareTo(str3);
int k = str1.compareTo(str4);
System.out.println(i); //-1 底层是数组,数组中一个一个的比较 c
System.out.println(j); //0 一个一个的比较,都相同 返回0
System.out.println(k); //-1 f
String类的方法,去空格,替换,切割
// String trim() 去掉字符串两边的空格,中间的空格不去掉
String str =" aa c bb d ";
String s = str.trim();
System.out.println(s); //aa c bb d
//String []split("规则字符串") 对字符串进行切割
String str1Split ="aa,bb,cc,dd";
String[] strings = str1Split.split(",");
for(int i =0; i< strings.length;i++){
System.out.println(strings[i]); // aa bb cc dd
}
//String replace(String oldString,String newString)替换字符串
String strReplace = "how are you ?";
String replace = strReplace.replace("o", "ee");
System.out.println(replace); //heew are yeeu ?
String 类 正则表达式相关
字符类 :
[abc]
字符串的这个位置只能是abc[^abc]
字符串的这个位置不能是abc[a-zA-Z]
字符串的这个位置必须是字母,52个[^a-zA-Z]
字符串的这个位置必须不能是字母,52个数字类:
[0-9]
字符串的这个位置只能是数字[^0-9]
字符串的这个位置不能是数字[\d]
等同于 [0-9]
[\D]
等同于 [^0-9]
预定义字符 :
[\d]
等同于 [0-9]
[\D]
等同于 [^0-9]
[\w]
文字字符,包含数字,字母,下划线 [a-zA-Z0-9_]
[\W]
文字字符,不能包含数字,字母,下划线 [^a-zA-Z0-9_]
数量词 :
String 正则匹配校验
/**
* 检查邮箱
* 规则需求 :
* @ 前面 : 可以是字母,数字,_
* @ 后面 : 数字,字母 sina qq 126 1393 yahoo gmail
* . 固定 : com cn org edu gov 字母
*/
public static void stringMethod2(){
String email = "[email protected]";
// "[a-zA-Z0-9] == [\\w] \\两个\其中一个代表转义"
//"[\\w]+" 表示[\w] 匹配一次或多次
//(\\.[a-z]+)+ 表示(\\.[a-z]+)这个匹配组匹配一次或多次 比如.com.cn
String reg = "[\\w]+@[a-z0-9]+(\\.[a-z]+)+";
boolean b = email.matches(reg);
System.out.println(b);
}
/**
* 正则表达式检查手机号是否合法
* 规则需求
* 开头必须是1,长度固定11
* 第二位3 4 5 6 7 8 9
* 第三位 必须是都是数字
*/
public static void stringMethod(){
String tel = "13800138000";
//定义正则的规则,也是字符串
String regex = "1[3459678][0-9]{9}";
//正则规则,和字符串校验
//String类的方法 matches()
boolean b = tel.matches(regex);
System.out.println(b);
}
public static void stringMethod3(){
String str = "as123d387654w5465fasfr234567sa";
String[] strings = str.split("\\d+");
for (int i = 0; i < strings.length; i++) {
System.out.println(strings[i]);
} //as d w fasfr sa
System.out.println("================");
String ip = "192.....168.....35.121";
String[] ipArray = ip.split("\\.+");
for (int i = 0; i < ipArray.length; i++) {
System.out.println(ipArray[i]);
}// 192 168 35 121
}
public static void stringMethod4(){
String str = "as123d387654w5465fasfr234567sa";
//字符串中的所有数组,换成#
String repString = str.replaceAll("\\d+","#");
System.out.println(repString);//as#d#w#fasfr#sa
String first = str.replaceFirst("\\d+","#");
System.out.println(first);//as#d387654w5465fasfr234567sa
}
String Builder类
程序开发中,常常碰到字符串连接的情况,直接的方式是通过"+"符号来实现String的直接拼接,但是这种方式每执行一次都会创建一个String对象,效率低耗时又浪费空间。使用StringBuilder类就可以避免这种问题的发生
public final class StringBuilder
extends Object
implements Serializable, CharSequence
一个可变的字符序列(字符数组)。 此类提供与StringBuffer的API,但不保证同步。
创建对象的时候,StringBuilder中的数组的初始化长度为16个字符
StringBuilder自动的进行数组的扩容,新数组实现,原来数组的中元素复制到新的数组.
结论 : 无论怎么做字符串的操作,StringBuilder内部永远只有一个数组
StringBuilder类是线程不安全的类,运行速度快
StringBuffer是线程安全的类,运行速度慢,多线程的程序使用
两个类的构造方法和其他的方法一模一样.
StringBuilder builder = new StringBuilder(20);
builder.append("helo");
System.out.println(builder); //helo
builder.insert(3,"world");
System.out.println(builder);//helworldo
StringBuilder builder1 = new StringBuilder(16);
System.out.println(builder1.append("hello").append("world").append(" ").append("over"));// helloworld over