JavaSE学习总结(八)常用类(上)/Object类/==与equals方法的区别/浅克隆的特点/Scanner类/String类/String两种创建对象方式的区别/String类的各种功能
常用类(上)
一、Object类
(一)概述
是类层次结构的根类,所有类都直接或者间接地继承自该类
(二)构造方法
public Object();
(三)常见成员方法
1.hashcode()
public int hashCode();
1
(1)返回该对象的哈希码值。默认情况下,该方法会根据对象的地址来计算哈希码值。
(2)不同对象的hashCode()一般来说不会相同。但是,同一个对象的hashCode()值肯定相同。
(3)不是对象的实际地址值,可以理解为逻辑地址值。
案例演示
public class MyTest {
public static void main(String[] args) {
// java.lang 包下的类,可以不用导包
//创建Object类对象
Object obj = new Object();
System.out.println(obj);
int i = obj.hashCode();
System.out.println(i);
Object obj2 = new Object();
int i1 = obj2.hashCode();
System.out.println(i1);
}
}
2.getClass()
public final Class getClass();
1
(1)返回此 Object 的运行时类。
(2)可以通过Class类中的一个方法public String getName()
,获取对象的真实类的全名称。
案例演示
public class MyTest {
public static void main(String[] args) {
//万物皆对象,字节码文件也可以是一个对象
//Object.class 字节码文件加载进内存-----JVM就会为Object.class文件创建一个对象。
Object obj = new Object();
Class class1 = obj.getClass(); //返回Object.class这个字节码文件对象。
Object obj2 = new Object();
Class class2 = obj2.getClass();
Object obj3 = new Object();
Class class3 = obj3.getClass();
System.out.println(obj==obj2); //false
System.out.println(class1);
System.out.println(class1.getName());
System.out.println(class1==class2);
System.out.println(class2==class3);
}
}
3.toString()
public String toString();
(1)返回该对象的地址值的字符串表示形式。
toString()源代码:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
案例演示
public class MyTest {
public static void main(String[] args) {
Object obj = new Object();
String s = obj.toString(); //获取该对象的地址值的字符串表现形式
System.out.println(s);
Object obj2 = new Object();
System.out.println(obj2.toString());
}
}
(2)由于默认情况下地址值的数据对我们来说没有意义,一般建议重写toString方法。
怎么重写?一般是将该类的所有的成员变量数据返回即可
案例演示
public class MyTest{
public static void main(String[] args) {
Student student = new Student("张三", 23);
int i = student.hashCode();
System.out.println(i);
Class class1 = student.getClass();
System.out.println(class1.getName());
//一般情况下,我们自定义的类,都喜欢重写Object类toString()方法,让他打印成员变量的值,当然根据实际情况,可以打印其他任何内容
System.out.println(student.toString());
}
}
class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名:"+this.name+","+"年龄:"+this.age;
}
}
(3)直接输出对象的名称,其实就是调用对象的toString()方法
例如:
Object obj=new Object();
System.out.println(obj);//等价于System.out.println(obj.toString());
(4)IDEA自动重写
快捷键alt+insert 选toString() ,软件自动重写toString()方法
4.equals()
表示其他某个对象是否与此对象“相等”。
源代码:
public boolean equals(Object obj) {
return (this == obj);
}
(1)默认情况下比较的是对象的引用(地址值)是否相同。
(2)由于有时候比较对象的地址值没有意义,一般建议重写该方法。一般用于比较成员变量的值是否相等。
(3)==和equals()的区别:
==号是一个比较运算符,能比较基本数据类型和引用数据类型
- 比较基本数据类型,比较的是两个值是否相等
- 比较引用数据类型,比较的是两个对象的地址值是否相等
例子:int a=10
与 long b=10L
与 double c=10.0
都是相同的(为true),因为他们都指向地址为10的堆。
而equals方法最初是在所有类的基类Object中进行定义的,由equals的源码可以看出定义的equals与是等效的,不同的原因就在于有些类(像String、Integer等类)对equals进行了重写,但是没有对equals进行重写的类(比如我们自定义的类)就只能从Object类中继承equals方法,其equals方法与是等效的,除非我们在此类中重写equals。
案例演示
public class MyTest {
public static void main(String[] args) {
Object obj = new Object();
Object obj2 = new Object();
System.out.println(obj == obj2);//判断两个对象的地址值是否相同
// boolean equals (Object obj) 判断两个对象的地址值是否相同
boolean b = obj.equals(obj2);
System.out.println(b);
System.out.println("---------------------");
Student s1 = new Student("张三", 23);
Student s2 = new Student("张三", 23);
System.out.println(s1 == s2);//判断两个对象的地址值是否相同
System.out.println(s1.equals(s2));//判断两个对象的地址值是否相同
System.out.println(s1.equals(s1));
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
class Teacher {
}
s1.equals(s2) 比较两个对象的地址值,是否相同,对我来说意义不大,我认为只要两个对象的成员变量值一样,这两个对象就一样,那么我就得重写父类的equals()方法,让他去比较两个对象的成员变量的值是否相同,重写如下:
public class MyTest {
public static void main(String[] args) {
Student s1 = new Student("张三", 23);
Student s2 = new Student("张三", 23);
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s1));
System.out.println(s1.equals(new Teacher()));
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
//如果是自己跟自己比,直接就是true
if (this == obj) {
return true;
}
//如果是两个不同对象比较,则比较成员变量的值是否相同
//首先需要判断传进来的这个obj是否存在,且obj是不是Student类型的?
//instanceof 判断一个引用,是否是该类型的一个引用
if (obj==null||!(obj instanceof Student)) {
return false;
}//也可以写成if(obj==null||getClass() != obj.getClass()){return false;}
//向下转型
//如果不向下转型,无法通过obj直接使用Student类的成员变量name和age进行比较
Student stu = (Student) obj;
return this.name.equals(stu.name) && this.age == stu.age;
//不能写成return this.name==stu.name && this.age == stu.age;
//因为name是String类型,而String是引用类型,==号比较引用类型比较的是地址值
//String(字符串类)重写了equals方法,比较两个字符串的内容是否相同
}
}
class Teacher {
}
5.clone()
clone即拷贝,用于拷贝对象的各个属性
案例演示1
public class MyTest {
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog();
dog.name="小黑";
dog.age=10;
System.out.println(dog);
System.out.println(dog.name);//小黑
System.out.println(dog.age);//10
//protected Object clone () 创建并返回此对象的一个副本。
//由于Object类的clone方法是被protected修饰,因此不同包下无关类访问不到
//但是不同包下子类可以访问,因此子类需要重写clone方法,无关类就能通过对象调用clone了
Dog dog1= (Dog) dog.clone();
System.out.println(dog1);//克隆后虽然所有属性都拷贝了一份,但是指向的是不同的空间,地址值不同
System.out.println(dog1.name);//小黑
System.out.println(dog1.age); //10
}
}
//Object类本身不实现Cloneable接口,所以在类为Object的对象上调用clone方法会导致运行时抛出异常CloneNotSupportedException
//因此要想clone成功,则类必须实现Cloneable接口,以指示 Object.clone()方法可以合法地对该类实例进行按字段复制。
//Cloneable接口没有任何抽象方法,是一个标记接口
class Dog extends Object implements Cloneable{
String name="小白";
int age=23;
//子类需要重写clone方法,无关类就能通过对象调用clone了
@Override
protected Object clone() throws CloneNotSupportedException {
//重写逻辑还是用父类的clone逻辑
return super.clone();
}
}
对象的克隆分为浅克隆和深克隆,使用clone()方法采用的是浅克隆的方式
案例演示2
浅克隆的理解,猜猜最后的输出
public class MyTest {
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog();
dog.name="旺财";
dog.age=10;
Dog dog1 = (Dog) dog.clone();
dog1.name="小黑";//克隆后指向不同空间,因此更改属性也是更改各自的
dog1.age=19;
System.out.println(dog.name);
System.out.println(dog.age);
System.out.println(dog1.name);
System.out.println(dog1.age);
System.out.println("----------浅克隆----------");
DogFood dogFood = new DogFood("渴望");
Dog dog2 = new Dog("小白", 3, dogFood);
dog2.dogFood.name = "馋不腻";
Dog dog3 = (Dog) dog2.clone();
dog3.dogFood.name = "爱肯拿";
System.out.println(dog2.dogFood.name);
System.out.println(dog3.dogFood.name);
//对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把另外一个对象也克隆一份。
//深克隆:克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象 克隆的时候不仅要克隆这个对象,还有克隆这个对象里面维护的那个对象
}
}
class Dog implements Cloneable {
public String name;
public int age;
public DogFood dogFood;//成员变量还有另外一个类
public Dog() {
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Dog(String name, int age, DogFood dogFood) {
this.name = name;
this.age = age;
this.dogFood = dogFood;
}
}
class DogFood {
public String name;
public DogFood(String name) {
this.name = name;
}
}
克隆后不是各自指向一个空间,更改属性也是更改各自的吗?为什么dog2.dogFood.name也变成了“爱肯拿”呢?画个内存图就知道了:
使用clone()方法的注意事项:
- clone()的权限修饰符是受保护的,在用的时候,该类必须重写clone(),并把该方法的权限修饰符改为public
- 如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口。
- Cloneable接口只不过是一个标识接口而已,其中没有任何方法。
- 对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把另外一个对象也克隆一份。
- 对象的浅克隆不会调用到构造方法。
对象的深克隆(后面讲):采用IO流来实现 使用 ObjectOutputStream 将对象写入文件中,然后再用ObjectInputStream读取回来(克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,克隆的时候不仅要克隆这个对象,还要克隆这个对象里面维护的那个对象)
二、Scanner类
一)Scanner的概述
JDK5以后用于获取用户的键盘输入
(二)Scanner的构造方法
public Scanner(InputStream source);
构造一个新的 Scanner,它生成的值是从指定的输入流扫描的。
System类下有一个静态的字段:
public static final InputStream in;
标准的输入流,此流已打开并准备提供输入数据,通常此流对应着键盘录入。
因此,通常利用构造方法获取用户键盘输入表示为:Scanner scanner = new Scanner(System.in);
(三)hasNextXxx()和nextXxx()方法
hasNextXxx()
判断输入的下一个是否是某种类型的元素,其中Xxx可以是Int、Long、Float、Double、Line(字符串)等。判断输入的下一个是否是字符串,也可以用hasNext()
nextXxx()
获取下一个输入项。Xxx的含义和上个方法中的Xxx相同。获取字符串也可以用next()
案例演示1
import java.io.InputStream;
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
InputStream is = System.in;
//类 System
//public static final InputStream in;“标准”输入流。此流已打开并准备提供输入数据。通常,此流对应于键盘输入
//Scanner(InputStream source) 构造一个新的 Scanner,它生成的值是从指定的输入流扫描的。
Scanner scanner = new Scanner(is);
System.out.println("请输入一个字符串:");
String s = scanner.nextLine();
System.out.println("你输入的是: "+s);
}
}
案例演示2
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
//当你使用Scanner先用nextInt()录入整数后用nextLine()录入字符串时,你会发现,我还没有输入字符串,程序就结束了
//其实它把你上次敲的回车换行符当做字符串已经录入了,但是这不是我想要的效果,怎么解决?
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数:");
int num = sc.nextInt();
System.out.println("你输入的数字是:"+num);
System.out.println("请输入一个字符串:");
String s = sc.nextLine();
System.out.println("你输入的字符串是:"+s);
}
}
方法一:可以在录入字符串之前,再创建一个Scanner新对象
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数:");
int num = sc.nextInt();
System.out.println("你输入的数字是:"+num);
sc=new Scanner(System.in);//方法一,可以在录入字符串之前,再创建一个新对象
System.out.println("请输入一个字符串:");
String s = sc.nextLine();
System.out.println("你输入的字符串是:"+s);
}
}
方法二:用next()方法接收字符串的录入
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数:");
int num = sc.nextInt();
System.out.println("你输入的数字是:"+num);
System.out.println("请输入一个字符串:");
String s = sc.next();//方法二:用next()方法接收字符串的录入
System.out.println("你输入的字符串是:"+s);
}
}
案例演示3
next()和nextLine():
nextLine()可以获取完整的字符串录入包括空格
而next()遇到第一个空格后,空格后面的内容就不录入
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String s=sc.next(); //录入的字符串中,遇到第一个空格后,空格后面的内容就不录入
System.out.println("你输入的字符串:"+s);
}
}
思考题:请用户输入数字,如果输入的不是数字,给予提示并重新输入。
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
System.out.println("请输入一个数字:");
while(true){
Scanner sc = new Scanner(System.in);
if(sc.hasNextInt()){
int i = sc.nextInt();
System.out.println("你输入的数字是:"+i);
break;
}else{
System.out.println("你输入的不是数字,请重新输入:");
}
}
}
}
三、String类
(一)什么是字符串
- String 类代表字符串
- 字符串是由多个字符组成的一串数据(字符序列)
- 字符串可以看成是字符数组(String类是的本质是字符数组char[])
(二)构造方法
public String()
:空参构造
public String(String original)
:把字符串常量值转成字符串
public String(byte[] bytes)
:把字节数组转成字符串(ascii码)
public String(byte[] bytes,int index,int length)
:把字节数组的一部分转成字符串(index:表示的是从第几个索引开始, length表示的是长度)
public String(char[] value)
:把字符数组转成字符串
public String(char[] value,int index,int count)
:把字符数组的一部分转成字符串
案例演示
public class MyTest {
public static void main(String[] args) {
//1.空参构造方法:String()
//初始化一个新创建的 String 对象,使其表示一个空字符序列。
String a = new String(); //创建一个空的字符串对象
System.out.println(a.toString());//字符串重写了toString方法,打印的是字符串的内容
//2.String(String original)把字符串常量值转成字符串
//初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
String b = new String("abc");
System.out.println(b.toString());//字符串重写了toString方法,打印的是字符串的内容
byte[] bytes={97,98,99,100};
//3.public String( byte[] bytes):把字节数组转成字符串
String s = new String(bytes);//将ASCII码对应值转换成了字符串
System.out.println(s);
//4.public String( byte[] bytes, int index, int length):把字节数组的一部分转成字符串(index:表示的是从第几个索引开始, length表示的是长度)
s=new String(bytes,2,2);//从索引为2处开始,转2个字节
System.out.println(s);
char[] ch ={'a','b','c','你','好',100};
//5.public String( char[] value):把字符数组转成字符串
String s1 = new String(ch);
System.out.println(s1);
//6.public String( char[] value, int index, int count):把字符数组的一部分转成字符串
s1=new String(ch,3,2); //从索引为3处开始,转2个字符
System.out.println(s1);
}
}
(三)String类注意事项
- String类不可被继承(
public final class String
) - Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
- 字符串是常量,它们的值一旦被创建,就不能被改变。
- String类重写了toString方法,打印的是字符串的内容
案例演示1
public class MyTest {
public static void main(String[] args) {
//String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
String s = "abc";
System.out.println(s);
}
}
由于字符串字面值(如"abc")都是String类的实例对象,因此String类创建对象除了可以用new来创建,也可以通过上述方式创建。
案例演示2
public class MyTest {
public static void main(String[] args) {
//字符串是常量;它们的值在创建之后不能更改。
String s = "hello" ;
s = "world" + "java";
System.out.println(s);
}
}
不是说创建之后不能更改吗?其实不能更改的是字符串的值本身,而引用变量可以改变。
思考题1
String str=new String("abc");
这行代码创建了几个String对象?
答:1个或2个。
(1)首先在堆中(不是常量池)开辟一个内存空间,并让str引用指向该空间
(2)在字符串常量池中查看,是否存在内容为"abc"字符串对象
(3)若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来(1个)
(4)若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来(2个)
思考题2
String str="abc";
我们知道这行代码创建了一个String对象。
那这里呢?String a="abc"; String b="abc";
答:还是一个。
再看看这里呢?String a="ab"+"cd";
通过编译器优化后,得到的结果是String a="abcd"
答:零个或一个。如果字符串常量池中存在abcd,则该语句并不会创建对象,只是将字符串常量池中的引用返回而已;如果字符串常量池中不存在abcd,则会创建并放入字符串常量池,并返回引用。
如果用String s=new String("abcd")
,不管常量池里有没有"abcd",它都会在堆中重新分配一块内存,定义一个新的对象。因此提倡大家用引号包含文本的方式来创建String对象以提高效率,这也是我们在编程中常采用的。
思考题3
String s="hello"+"world";
//编译器优化后,直接将helloworld对象放入字符串池中。
System.out.println(s=="helloworld");
//结果是true;
String str1="hello";
String str2="world";
String s = str1+str2;
System.out.println(s=="helloworld");
//结果是啥?
答案是false。
JVM对形如String str="hello"+"world";
根据编译器合并已知量的优化功能,在池中开辟一块空间,存放合并后的String常量"helloworld",但是它是在编译时刻那么做的;而String s = str1+str2;
是在运行时刻才能知道,也就是说str1+str2是在堆里创建的, s引用当然不可能指向字符串常量池里的对象,s引用指向堆内存。
String s=str1+"world";
//不放在字符串池中,而是在堆中分配。
System.out.println(s=="helloworld");
//结果是啥?
答案是false。
总之,创建字符串常用的两种方式:
1.""创建的字符串在字符串常量池中。
2.new 创建字符串时,首先查看池中是否有相同的字符串,如果有则拷贝一份放到堆中,然后返回堆中的地址;如果池中没有则在堆中创建一份,然后返回堆中的地址,
3.在对字符串赋值时,如果右操作数含有一个或一个以上的字符串引用时,则在堆中再建立一个字符串对象,返回堆中的引用。 如:String s= str1+"world";
思考题4
String s = new String(“abcd”);
和String s = “abcd”;
的区别是什么?
答:
String s="abcd"
是一种非常特殊的形式,和new 有本质的区别。它是java中唯一不需要new 就可以产生对象的途径。以String s="abcd";
形式赋值在java中叫直接量,它是在常量池中而不是象new一样放在压缩堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abcd"的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个"abcd",下一次如果有String s1 = "abcd";
又会将s1指向"abcd"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象。而String s = new String("abcd");
和其它任何对象一样.每调用一次就产生一个对象,只要它们调用。
字面量创建字符串会先在字符串池中找,看是否有相等的对象,没有的话就在堆中创建,把地址驻留在字符串池;有的话则直接用池中的引用,避免重复创建对象。
new关键字创建时,前面的操作和字面量创建一样,只不过最后在运行时会创建一个新对象,变量所引用的都是这个新对象的地址。
(四)length()
public int length()
:返回此字符串的长度。
案例演示
public class MyTest {
public static void main(String[] args) {
//1
String s = new String("abc");
int length = s.length();
System.out.println(length);
//2.由于所有字符串字面值都作为此类的实例实现,也可以用字符串直接调用方法
int length1 = "abcde".length();
System.out.println(length1);
}
}
(五)String类的判断功能
public boolean equals(Object obj):
比较字符串的内容是否相同,区分大小写
public boolean equalsIgnoreCase(String str):
比较字符串的内容是否相同,忽略大小写
public boolean contains(String str):
判断字符串中是否包含传递进来的字符串
public boolean startsWith(String str):
判断字符串是否以传递进来的字符串开头
public boolean endsWith(String str):
判断字符串是否以传递进来的字符串结尾
public boolean isEmpty():
判断字符串的内容是否为空串""。
案例演示
public class MyTest {
public static void main(String[] args) {
//public boolean equals (Object obj):比较字符串的内容是否相同, 区分大小写
boolean b = "abc".equals("ABC");
System.out.println(b);
//public boolean equalsIgnoreCase (String str):比较字符串的内容是否相同, 忽略大小写
b = "abc".equalsIgnoreCase("ABC");//不区分大小写的比较
System.out.println(b);
//public boolean contains (String str):判断字符串中是否包含传递进来的字符串
b = "I love Java".contains("Java");
System.out.println(b);
//public boolean startsWith (String str):判断字符串是否以传递进来的字符串开头
b = "欧阳娜娜".startsWith("欧阳");
System.out.println(b);
//public boolean endsWith (String str):判断字符串是否以传递进来的字符串结尾
b = "13900008888".endsWith("8888");
System.out.println(b);
//public boolean isEmpty ():判断字符串的内容是否为空串 ""。
b = "".isEmpty();
System.out.println(b);
//b = "".length() == 0 ? true : false;
//System.out.println(b);
}
}
(六)String类的获取功能
public int length()
:获取字符串的长度。
public char charAt(int index)
:获取指定索引位置的字符
public int indexOf(int ch)
:返回指定字符在此字符串中第一次出现处的索引。
public int indexOf(String str)
:返回指定字符串在此字符串中第一次出现处的索引。
public int indexOf(int ch,int fromIndex)
:返回指定字符在此字符串中从指定位置后第一次出现处的索引。
public int indexOf(String str,int fromIndex)
: 返回指定字符串在此字符串中从指定位置后第一次出现处的索引。
public int lastIndexOf(int ch)
:返回在指定字符在此字符串中最后一次出现的索引。
public int lastIndexOf(int ch, int fromIndex)
:返回指定字符在此字符串中从开头到指定位置中最后一次出现处的索引。
public int lastIndexOf(String str)
:返回指定字符串在此字符串中最后一次出现的索引。
public int lastIndexOf(String str, int fromIndex)
:返回指定字符串在此字符串中从开头到指定位置中最后一次出现处的索引。
public String substring(int start)
:从指定位置开始截取字符串,默认到末尾。
public String substring(int start,int end):
从指定位置开始到指定位置结束截取字符串。(含头不含尾)
案例演示
public class MyTest {
public static void main(String[] args) {
String s = "七月的风,八月的雨";
//public int length ():获取字符串的长度。
System.out.println(s.length());
//public char charAt ( int index):获取指定索引位置的字符
char ch = s.charAt(s.length() - 1);
System.out.println(ch);
//public int indexOf ( int ch):返回指定字符在此字符串中第一次出现处的索引。
int index=s.indexOf('月');
System.out.println(index);
//public int indexOf (String str):返回指定字符串在此字符串中第一次出现处的索引。
index = s.indexOf("月的");
System.out.println(index);
//如果没有找到,通常会返回-1
index = s.indexOf("九月");
System.out.println(index);
//public int indexOf ( int ch, int fromIndex):返回指定字符在此字符串中从指定位置后第一次出现处的索引。
index = s.indexOf('月', 5);
System.out.println(index);
//public int indexOf (String str,int fromIndex):返回指定字符串在此字符串中从指定位置后第一次出现处的索引。
index = s.indexOf("月的",5);
System.out.println(index);
//public int lastIndexOf(int ch):返回在指定字符在此字符串中最后一次出现的索引。
index = s.lastIndexOf('月');
System.out.println(index);
//public int lastIndexOf(int ch, int fromIndex):返回指定字符在此字符串中从开头到指定位置中最后一次出现处的索引。
index = s.lastIndexOf('的',3);
System.out.println(index);
//public int lastIndexOf(String str):返回指数在这个字符串的指定子字符串中最后一次出现的索引。
index = s.lastIndexOf("月的");
System.out.println(index);
//public int lastIndexOf(String str, int fromIndex):返回指定字符串在此字符串中从开头到指定位置中最后一次出现处的索引。
index = s.lastIndexOf("月的",5);
System.out.println(index);
//public String substring ( int start):从指定位置开始截取字符串,默认到末尾,返回的是截取到的字符串。
String s1 = s.substring(5);
System.out.println(s1);
//public String substring ( int start, int end):从指定位置开始到指定位置结束截取字符串。
s1=s.substring(5,7);//含头不含尾
System.out.println(s1);
s1 = s.substring(0, s.indexOf('风') + 1);
System.out.println(s1);
}
}
判断此字符串中某个字符是否只出现了一次
public class MyTest {
public static void main(String[] args) {
String s="七月的风,八月的雨";
boolean b = s.indexOf('雨') == s.lastIndexOf('雨');
System.out.println(b);
}
}
(七)字符串的遍历
案例演示
public class MyTest {
public static void main(String[] args) {
String str = "七月的风,八月的雨";
for (int i = 0; i < str.length(); i++) {
System.out.println(str.charAt(i));
}
}
}
(八)统计字符串中不同类型字符个数
方法一
public class MyTest {
public static void main(String[] args) {
String str = "AFDFDdfdfdfAFDFd2113232safsdfsdf0123asdfasdfAA";
int a = 0;
int b = 0;
int c = 0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch >= 'A' && ch <= 'Z') {
a++;
} else if (ch >= 'a' && ch <= 'z') {
b++;
} else if (ch >= '0' && ch <= '9') {
c++;
}
}
System.out.println("大写字母有" + a + "个");
System.out.println("小写字母有" + b + "个");
System.out.println("数字字符有" + c + "个");
}
}
方法二
类Character中有这几个静态方法:
static boolean isLowerCase ( char ch)
确定指定字符是否为小写字母。
static boolean isUpperCase ( char ch)
确定指定字符是否为大写字母。
static boolean isDigit ( char ch)
确定指定字符是否为数字。
public class MyTest {
public static void main(String[] args) {
String str = "AFDFDdfdfdfAFDFd2113232safsdfsdf0123asdfasdfAA";
int a = 0;
int b = 0;
int c = 0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (Character.isUpperCase(ch)) {
a++;
} else if (Character.isLowerCase(ch)) {
b++;
} else if (Character.isDigit(ch)) {
c++;
}
}
System.out.println("大写字母有" + a + "个");
System.out.println("小写字母有" + b + "个");
System.out.println("数字字符有" + c + "个");
}
}
(九)String类的转换功能
public byte[] getBytes()
:把字符串转换为字节数组。
public char[] toCharArray()
:把字符串转换为字符数组。
public static String valueOf(char[] chs)
:把字符数组转成字符串。
public static String valueOf(int i)
:把int类型的数据转成字符串。
valueOf方法还有long、float、double、Object等等类型。
public String toLowerCase()
:把字符串转成小写。
public String toUpperCase()
:把字符串转成大写。
public class MyTest {
public static void main(String[] args) {
//public byte[] getBytes ():把字符串转换为字节数组。
byte[] bytes = "abcd".getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
//把字节数组转成字符串
String s1 = new String(bytes);
System.out.println(s1);
String str="hello world";
//把字符串转换成字符数组,传统方法
//char[] ch=new char[str.length()];
//for (int i = 0; i < str.length(); i++) {
// ch[i]= str.charAt(i);
//}
public char[] toCharArray ():把字符串转换为字符数组。
char[] ch = str.toCharArray();
for (char c : ch) {
System.out.print(c);
}
System.out.println();
//public static String valueOf ( char[] chs):把字符数组转换成字符串
String s2 = String.valueOf(ch);//法一
System.out.println(s2);
String s3 = new String(ch);//法二
System.out.println(s3);
//public static String valueOf ( int i):把int类型的数据转成字符串。
String s4 = String.valueOf(12345);
System.out.println(s4);
//public String toUpperCase ():把字符串转成大写。
String s5 = "abcd".toUpperCase();
System.out.println(s5);
//public String toLowerCase ():把字符串转成小写。
String s6 = "ABCD".toLowerCase();
System.out.println(s6);
String s7 = String.valueOf(new Object());
System.out.println(s7);//返回Object类对象的地址值的字符串形式
}
}
(十)String类的其他功能
1.String的替换功能
public String replace(char old,char new)
将指定字符进行互换
public String replace(String old,String new)
将指定字符串进行互换
2.String的去除字符串两端空格
public String trim()
去除两端空格
3.String的按字典顺序比较两个字符串
public int compareTo(String str)
会对照ASCII 码表 从第一个字母开始进行减法运算 返回的就是这个减法的结果(调用者减去传入者)
- 如果字符串相等返回值为0,不等返回其他数值。
比较方法是先比较对应字符的大小(ascii码值),从第一个字母开始比较。 - 如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值(ascii码值)(负值:前字符串的值小于后字符串;正值:前字符串大于后字符串)
- 如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较。以此类推,直至比较的字符或被比较的字符有一方全比较完,这时就比较字符串的长度。
public int compareToIgnoreCase(String str)
跟上面一样 只是忽略大小写的比较
案例演示
public class MyTest {
public static void main(String[] args) {
//字符串中替换的方法
String s = "七月的风,八月的雨".replace('雨', '云');
System.out.println(s);
String s1 = "七月的风,八月的雨".replace("八月", "九月");
System.out.println(s1);
String s2 = "七月的风,八月的雨".replace("七月", "六月").replace("八月", "九月");
System.out.println(s2);
//字符串去除两端空格的方法
String trim = " abc ".trim();
System.out.println(trim);
//对比字符串,通过字典顺序去比较,返回的值是 ASCII 码的差值,调用者减去传入者
int i = "abc".compareTo("Abc");
System.out.println(i);
//通过长度去比
int i1 = "abc".compareTo("a");
System.out.println(i1);
int i2 = "abc".compareTo("abcde");
System.out.println(i2);
//忽略大小写的比较
int abc = "Abc".compareToIgnoreCase("aBC");
System.out.println(abc);
}
}
4.String的拼接功能及案例演示
public String concat(String str)
:把字符串拼接。可以替代加号
案例演示
public class MyTest {
public static void main(String[] args) {
String c="abc".concat("ccc").concat("aaa").concat("abcc");
System.out.println(c);
}
}
思考题1:把一个字符串的首字母转成大写,其余为小写。
public class MyTest {
public static void main(String[] args) {
String s="jsdkfsjDddSKKJADJKsd";
String s1 = s.substring(0, 1).toUpperCase().concat(s.substring(1).toLowerCase());
System.out.println(s1);
}
}
思考题2:
去除一个字符串的两端空格和中间空格
例如String str = " asdfd sf asf dsa d f ";
方法一:创建一个新字符串str2初始化为空串,通过循环遍历str将非空格部分赋给新串并输出
public class MyTest {
public static void main(String[] args) {
//去除一个字符串的两端空格和中间空格
String str=" asdfd sf asf dsa d f ";
String str2="";
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i)==' '){
continue;
}else{
str2+=str.charAt(i);
}
}
System.out.println(str2);
}
}
方法二:将空格替换为空串
public class MyTest {
public static void main(String[] args) {
//去除一个字符串的两端空格和中间空格
String str=" asdfd sf asf dsa d f ";
String r = str.replace(" ", "");
System.out.println(r);
}
}
思考题3:只去掉字符串左边的空格
public class MyTest {
public static void main(String[] args) {
String s=" abc ";
String s1="";
for (int i = 0; i < s.length(); i++) {
if(s.charAt(i)!=' '){
s1=s.substring(i);
break;
}
}
System.out.println(s1);
}
}
思考题4:统计大串中小串出现的次数
方法一
public class MyTest {
public static void main(String[] args) {
String maxStr="woaijavawozhenaijavawozhendeaijavawozhendehenaijavawoaijava";
String minStr="java";
int count=0;
int index=0;
while((index=maxStr.indexOf(minStr))!=-1){
count++;
maxStr=maxStr.substring(index+minStr.length());
}
System.out.println("Java出现的次数:" + count + "次");
}
}
方法二
public class MyTest {
public static void main(String[] args) {
String maxStr="woaijavawozhenaijavawozhendeaijavawozhendehenaijavawoaijava";
String minStr="java";
int count=0;
String newStr = maxStr.replace("java", "0");
for (int i = 0; i < newStr.length(); i++) {
if(newStr.charAt(i)=='0'){
count++;
}
}
System.out.println("Java出现的次数:" + count + "次");
}
}