全名称:java.lang.Object
Object类是所有类的默认父类,无法使用extends继承
Class声明的类都有一个父类Object类
1.因为Object类是所有类的父类,使用Object引用来接收所有的类型,参数最高统一化!!!
void fun(Object obj){
}
Object obj1 = new Person();
Object obj2 = new String();
Object obj3 = new Dog();
Java中所有的类型都可以发生向上转型为Object类型!
2.Object类中的所有方法子类全都继承了下来
之所以System.out.println(任意的引用类型) => 默认都调用了toString()方法
@Override
public String toString() {
return "Dog类的toString方法";
}
Dog dog = new Dog();
System.out.println(dog);
//结果
Dog类的toString方法
equlas:
3.Java中的引用数据类型比较要使用equlas方法 ,"==" 比较的是地址值!!!
"=="比较的是数值,而对于引用类型来将保存的是地址值
//Object类中的equals方法
public boolean equals(Object obj) {
return (this == obj);
}
此时我们想判断两个引用类型是否相等就需要覆写equals方法!!!
public class Student {
String name ;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
//向上转型 O = student2,Object里面没有stu2独有的name和age
所以要向下转型!!!才能比较!!!
public boolean equals(Object o) {
if(this == o){
return true;
}
//防止发生类型转换异常
if(o instanceof Student){
Student s1 = (Student) o; //String类型可以直接调用父类的equals方法比较
return this.age == s1.age && this.name.equals(s1.name);
}
// 比较的都不是一个东西
学生和狗不能比较!
return false;
}
}
public class Test {
static String s1 = "wu";
static String s2 = "wu";
public static void main(String[] args) {
Student student1 = new Student("张三",18);
Student student2 = new Student("张三",18);
System.out.println(student1.equals(student2));
System.out.println(s1.equals(s2));
}
}
//结果
true
true
3.JDK对Object类做了扩展
Object类可以接收所以引用数据类型的对象(接口,数组,类)
// 接口引用
ITest i1 = new TestImpl();
//整形数组引用
int[] data = new int[10];
//只有是引用类型,都可以使用Object来接收
Object obj1 = i1;
Object obj2 = data;
因此在Java中,若一个方法参数或者返回值类型是Object类型,说明该参数或返回值可以是任意引用数据类型(数组,类,接口)
除了8大基本类型没法用Object类来接收,所以类型都可以用Object来接收.
包装类应运而生
Comparable:
java.lang.Comparable:当一个类实现了Comparale接口,表示该类具备了可比较的能力!!!
由于Person这个类型是自定义类型,对于编译器来说,不像int类型大小一目了然
到底哪个Person对象大,哪个Person对象小,编译器无从得知.
要让Person具备比较能力,就需要让Person类实现Compareale接口,覆写抽象方法compareTo
//当一个类实现了Comparable接口,即这个类拥有了比较能力
public class Person implements Comparable{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Object o) {
if(this == o){
return 0;
}
if(o instanceof Person){
Person person = (Person) o;
//按升序排序 >0
//按降序排序<0,person.age - this.age即可
return this.age - person.age;
}
throw new IllegalArgumentException("不是Person类型,无法比较!");
}
}
public class ComparableTest {
public static void sort(Comparable[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
// if (arr[j] > arr[j + 1]) // swap
if (arr[j].compareTo(arr[j + 1]) > 0) {
// 前一个大于后一个,交换j和j + 1
Comparable temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
public static void main(String[] args) {
//people是一个Person类型的数组,创建了三个Person类型的变量
Person person = new Person("z",100);
Person person1 = new Person("f",18);
Person[] people = new Person[]{
//arr[0]
new Person("张三",17),
//arr[1]
new Person("李四",18)
};
Arrays.sort(people);
System.out.println(Arrays.toString(people));
}
}
Cloneable:
java.lang.Cloneable 克隆接口
什么是克隆接口?
原对象和新产生的对象是两个独立的对象,新产生的对象是通过原对象"拷贝"而来,属性值和原对象完全一致.
要让一个类具备可复制能力,实现Cloneable接口,覆写clone方法
当我让Animal这个类实现Cloneable这个接口时并没有强制要求覆写方法,这是为什莫哪?
答:类似Cloneable接口,把这种接口称之为"标记"接口,这个接口本身没有任何抽象方法,只有打上这个标记的子类才具备克隆的能力!
JVM在运行时会检查所有实现了Cloneable接口的子类,赋予其克隆的能力.
clone方法是Object提供的方法.
public class Animal implements Cloneable{
String name;
public Animal(String name) {
this.name = name;
}
}
public class Animal implements Cloneable{
String name;
public Animal(String name) {
this.name = name;
}
public Animal clone(){
Animal newAnimal = null;
try {
newAnimal = (Animal) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return newAnimal;
}
}
animal和clone之间没有任何关系,只是属性值相等
clone的产生是依赖于animal
public class CloneTest {
public static void main(String[] args) {
Animal animal = new Animal("zs");
Animal clone = animal.clone();
System.out.println(clone.name);
}
}
深浅拷贝:
只需要了解概念即可
浅拷贝:就是克隆的对象和原对象肚子里包含的其他对象是一个东西
深拷贝:就是克隆对象和原对象肚子里包含的其他对象也是克隆出来的
在Java中产生一个新对象有两种方式:
1.最常见的是通过构造方法产生对象
new 类(); 当有new关键字,就会在堆上开辟相应属性的空间,并给属性赋默认值
2.通过clone();产生对象,调用clone时,JVM会开辟与原对象内存大小完全相同的新空间,并将原对象的属性值复制一份.(不推荐)
String:
public final class String
implements java.io.Serializable, Comparable, CharSequence {
为什莫String类被find修饰?
答:被find修饰的类无法继承,String类不存在子类,这样就可以保证大家用到的String类仅此一个,大家都相同.
假设String允许继承,每个人都可以继承String类,修改它的方法等实现,继承和覆写带来灵活性的同时,也会带来子类行为不一致的问题(每个人的String功能不一致).
1.创建字符串的四种方式(最常用1and2):
(1).直接赋值
String str1 = "hello word"; //字符串字面量,也是字符串对象
(2).通过构造方法产生对象
String str2 = new String("hello word");
(3).通过字符数组产生对象
char[] data = new char[] {"a","b","c"}
String str = new String(data);
(4).通过String的静态方法valueOf(任意数据类型) ->转为字符串
String str = String.valueOf(10);
String str1 = "hello";
String str2 = str1;
在栈中:str1,str2 同时指向了堆中的"hello"
public class StringTest {
//"Hello"也是字符串的字面量,是一个新的字符串对象,str2实际上指向了新的字符串对象"Hello"
// str1仍旧指向"hello word"
public static void main(String[] args) {
String str1 = "hello word";
String str2 = str1;
str2 = "Hello";
System.out.println(str1);
}
}
2.字符串比较是否相等
//结果:true 说明了指向了同一块地址
public static void main(String[] args) {
String str1 = "hello word";
String str2 = "hello word";
System.out.println(str1 == str2);
}
//结果:false equals是区分大小写的比较
public static void main(String[] args) {
String str1 = "hello word";
String str2 = "Hello word";
System.out.println(str1.equals(str2));
}
//结果:true equalsIgnoreCase是不区分大小写的比较
public static void main(String[] args) {
String str1 = "hello word";
String str2 = "Hello word";
System.out.println(str1.equalsIgnoreCase(str2));
}
//这个变量由用户从浏览器输入
String useName = null;
//有可能引发空指针异常,牵扯到用户输入就要做判空处理
System.out.println(useName.equals("zs"));
//这样就可以避免useName为Null的问题
System.out.println("zs".equals(useName));
3.字符串常量池
使用直接赋值法产生字符串对象时,JVM会维护一个常量池,若该对象在常量池中不存在,则产生一个新的字符串对象加入字符串常量池中.
当继续使用直接赋值法产生字符串对象时,JVM发现该引用指向的内容在常量池中已经存在了,就不再创建新对象,而是引用已有对象.
String str1 = "hello"; //字符串常量第一次出现,JVM发现常量池中不存在,就把该对象加入到常量池
String str2 = "hello";
String str3 = "hello";
System.out.println(str1 == str2);//true
System.out.println(str2 == str3);//true
有new就有新空间,这三行代码产生四个字符串对象,其中一个在常量池,其余三个在堆
//三个引用指向了三个不同的对象
String str1 = new String("hello");//代码从右向左执行碰到"hello"就把它加入到常量池中
String str2 = new String("hello");
String str3 = new String("hello");
System.out.println(str1 == str2);//false
System.out.println(str2 == str3);//false
常量池这样设计的原因是什么?
答:所谓的"池"都是类似的思想
共享设计模式-节省空间(内存是一个非常紧张的资源),字符串产生之后大部分都用来输出处理,打印内容,"hello"为啥不整一个就好
数据库的连接池 线程池都是类似的思想!!!
String的intern方法
public native String intern();//这个方法有一个返回值
调用intern方法会将当前字符串引用指向的对象保存到字符串常量池中.
a.若常量池已经存在了该对象,就不会产生新对象,返回常量池中的String对象.
b.若当前常量池不存在该对象,就将该对象入池,返回入池后的地址,
String str1 = new String("hello");
//常量池中已经有了"hello",不在产生新的对象返回常量池中的对象(但是没有接收)
str1.intern();
String str2 = "hello";
System.out.println(str1 == str2);//false
String str1 = new String("hello");
str1 = str1.intern(); //接收了常量池中的字符串对象地址
String str2 = "hello";
System.out.println(str1 == str2); //true
char[] data = new char[]{'a','b','c'};
String str1 = new String(data);//这是字符数组,不会入常量池,将字符数组转化为String
str1.intern(); //并没有赋值,intern将"abc"放入到了常量池
String str2 = "abc";
System.out.println(str1 == str2); //true
4.String的不可变性
字符串的不可变指的是字符串对象的内容不可变,而不是字符串引用不能变!
这里的不可变指的是"hello" "word" "helloword" "!!!"
"helloword!!!" 这些字符串对象一旦声明后就无法修改内容
String str = "hello";
str = str + "word";
str += "!!!";
System.out.println(str);
为什么字符串的对象无法修改内容,而其它对象可以修改内容?
答:字符串底层是被find修饰的char类型的数组
5.如何修改字符串的内容
a.在运行时通过反射破话value数组的封装(不推荐)
b.更换使用StringBuilder或StringBuffer类(已经不是一个类型了)
StringBuilder:只会创建一个对象,若要频繁进行字符串的拼接使用StringBuilder的append方法
StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append("word");
sb.append("!!!");
System.out.println(sb);
StringBuilder类的具体使用:
a.StringBuilder类和String类是两个独立的类,StringBuilder类是为了解决字符串的拼接产生的.
b.因为String的对象内容无法修改,为了方便字符串的拼接 *** 作,产生了StringBuilder类,String Builder类的对象是可以修改的
String和StringBuilder之间的互相转换!!!
//String转换为StringBuilder
//1.使用StringBuilder的构造方法
StringBuilder sb = new StringBuilder("123");
//2.使用append方法
sb.append("hello");
sb.append("word");
sb.append("!!!");
//StringBuilder转换为String
String str = sb.toString
1.字符串反转 *** 作revers();
StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append("word");
System.out.println(sb.reverse());//drowolleh
2.删除指定范围数据 delete(int start,int end):[start,end)
StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append("word");
System.out.println(sb.delete(5,9));//hello
3.插入 *** 作 insert(int start,各种数据类型):插入后新数值的索引为start
StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append("word");
System.out.println(sb.insert(5,10));//hello10word
4.将字符数组的部分内容转换为字符串
char[] ch = new char[]{'a','b','c'};
//字符数组引用,起始位置,转换个数
String s = new String(ch,1,2);
System.out.println(s);//"bc"
5.取出字符串中指定索引字符
String str = "hello";
System.out.println(str.charAt(1));//e
6.将字符串中的内容转为字符数组String -> char[]
//String对象不可变!!!内容改不了!!!
String str = "hello";
//此时产生了一个新的字符数组,将字符串的内容复制过去
char[] data = str.toCharArray();
data[0] = 'H';
System.out.println(str); //hello
判断一个字符串是否由纯数字组成!!!
"123" = true
"123a" = false
String str1 = "123";
String str2 = "123a";
System.out.println(isNum(str1));
System.out.println(isNum(str2));
public static boolean isNum(String str){
char[] chars = str.toCharArray();
for(char s : chars){
if(s < '0' || s > '9'){
return false;
}
}
return true;
}
7.字符串和字节的相互转换 (将字符串保存到文件中或是通过网络传输都要用到字节数组)
String->byte[]
String str1 = "中国你好";
//将字符串以默认字节数组形式返回
byte[] data = str1.getBytes();
//按照指定的编码格式转为字节数组
byte[] gbks = str1.getBytes("gbk");
System.out.println(Arrays.toString(data));
System.out.println(Arrays.toString(gbks));
在UTF-8编码下一个汉字占3个字节
在gbk编码下,一个汉字占2个字节
[-28, -72, -83, -27, -101, -67, -28, -67, -96, -27, -91, -67]
[-42, -48, -71, -6, -60, -29, -70, -61]
byte[]->String
byte[] b = new byte[]{97,98,99};
String s = new String(b);
System.out.println(s); //abc
8.字符串的查找
String str1 = "helloword";
System.out.println(str1.contains("wo"));//true
String str1 = "helloword";
//查看字符串是否以指定的字符开头
System.out.println(str1.startsWith("hello"));
String str1 = "helloword";
//查看字符串是否以指定的字符串结尾
System.out.println(str1.endsWith("word"));
9.字符串的替换 *** 作
String类所有针对字符串的 *** 作都不会改变原字符串!!!字符串的不可变性!!!
String str1 = "helloworld";
//将字符串中所有l替换为_
System.out.println(str1.replaceAll("l","_"));//he__owor_d
//将字符串中第一个l替换为_
System.out.println(str1.replaceFirst("l","_"));//he_loworld
System.out.println(str1);//helloworld
10.字符串的拆分 *** 作
String str1 = "hello word hello rocker";
String[] s = str1.split(" ");
String[] s1 = str1.split(" ", 2);
System.out.println(Arrays.toString(s));//[hello, word, hello, rocker]
System.out.println(Arrays.toString(s1));//[hello, word hello rocker]
若字符串中没有指定的子串就返回原数组
a.你的拆分格式不存在
b.你的这个格式是个特殊字符,需要转义处理"\\."
String str = "192.168.1.1";
String[] data = str.split("\.");
System.out.println(Arrays.toString(data));//[192, 168, 1, 1]
11.字符串的截取
String str = "helloword";
//产生一个新的字符串,原字符串不变
System.out.println(str.substring(0,5));
public String trim():去掉字符串中的左右空格,保留中间空格
public String toUpperCase():字符串转大写
public String toLowerCase():字符串转小写
public int length():取得字符串长度
public boolean isEmpty():判断是否为空字符串,但不是null,而是长度为0
String str = " hello word ";
System.out.println(str.trim());//hello word
System.out.println(str.toUpperCase());// HELLO WORD
System.out.println("HELLO".toLowerCase());//hello
System.out.println("HELLO".length());//5
isEmpty():成员方法,只能判断字符串的长度是否为0,不能判断null
写一个方法将字符串的首字母大写处理 !!!
String str = "hello";
System.out.println(firstUpper(str));
public static String firstUpper(String str){
//1.判空处理
if(str == null || str.isEmpty()){
return null;
}
//边界条件
if(str.length() == 1){
return str.toUpperCase();
}
//此时str长度大于1
//截取+大写 *** 作
return str.substring(0,1).toUpperCase() + str.substring(1);
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)