1. Object类的equals()方法
比较两个对象(默认是比较地址值)是否相等
// 源代码:
public boolean equals(Object obj) {
return (this == obj);
}
想比较地址值之外其他的,比如两个对象的成员变量是否相同,那么子类应该重写equals()方法,
ctrl+o 选择equals 重写:
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
//判断两个引用,是不是同一种类型的引用
if (this.getClass() != o.getClass()) {
return false;
}
//向下转型
Student student = (Student) o;
return this.age == student.age &&
Objects.equals(this.name, student.name);
}
要向下转型,‘==’比不出来字符串字面上内容相不相同,如果要比较得调equals()方法,
考虑健壮性:用instanceof判断一个引用(对象),是不是该类型的一个引用(判断传入的类型和要比较的是否一致,不一致则直接不比较)或者用getClass()方法也可以,
考虑效率:如果自己和自己比较,直接return true。
==和equals()区别
==是一个比较运算符,即可以比较基本数据类型,也可以比较引用数据类型,比较基本数据类型比的是两个值是否相等,比较引用类型比较的是两个对象的地址值是否相等;
equals()是object类中的一个方法,只能比较引用类型,默认比较的是两个对象的地址值是否相等;
有些类(比如 String类会比较字面值)会认为父类Object类中equals方法默认比较方式意义不大,会对equals方法进行重写,我们自定义的类会重写,去比较两个对象成员变量值是否相等。
2. Object类的clone() 方法
clone()权限修饰符默认是受保护protected,要自己重写一下,只修改权限修饰符就可以了。
标记接口:Cloneable 其中没有任何抽象方法,这种接口我们称之为标记接口。目的就是给类打一个标记,让虚拟机支持克隆的操作。如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口,要为类实现该接口,Cloneable接口只不过是一个标识接口而已,没有任何方法。
深克隆、浅克隆:
浅克隆:调用clone方法就是浅克隆,只克隆了对象内维护的对象的地址值,对象的浅克隆也不会调用到构造方法的。对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把另外一个对象也克隆一份。
3. 常见对象之Scanner()
Scanner的概述:JDK5以后用于获取用户的键盘输入
Scanner的构造方法原理:
Scanner(InputStream source)
System类下有一个静态的字段:
public static final InputStream in; 标准的输入流,对应着键盘录入。
两个常用的方法:
public int nextInt():获取一个int类型的值
public String nextLine():获取一个String类型的值
public String next():获取一个String类型的值
当你先录入整数,然后使用nextLine()录入字符串时,会发现字符串没让你录入,原因就是你上次敲的回车换行默认被nextline()录入了,但这不是我们想要的效果
解决方式1:可以在录入字符串时,再创建一个Scanner对象,录入获取字符串,
package org.westos.demo2;
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数");
int i = sc.nextInt();
System.out.println(i);
System.out.println("请输入一个字符串");
//解决方式1:可以在录入字符字符串时,在创建一个Scanner对象。
sc = new Scanner(System.in);
String s = sc.nextLine();
//String s = sc.next();
System.out.println(s);
}
}
解决方式2:可以使用next()来录入字符串,但是不建议,因为这样不会录入空格,你输入的字符串中有空格,他在录入时,遇到的第一个空格后面的内容,
package org.westos.demo2;
import java.util.Scanner;
public class MyTest2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String s = sc.nextLine();
//解决方式2:可以使用next() 来录入字符串
//next() 你输入的字符串中有空格,那么他在录入时,遇到第一个空格后面的内容,不会录入进来
//String s = sc.next();
System.out.println(s);
}
}
hasNextXxx() :判断下一个是否是某种类型的元素,其中Xxx可以是Int,Double等。如果需要判断是否包含下一个字符串,则可以省略Xxx。
nextXxx() :获取下一个输入项。Xxx的含义和上个方法中的Xxx相同
/*sc.nextInt();
sc.nextDouble();
sc.nextLine();
录入某一指定类型的数据*/
练习:
package org.westos.demo2;
import java.util.Scanner;
public class ScannerUtils {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数");
getNumber(sc);
}
public static int getNumber(Scanner sc){
int num=0;
while (true) {
sc = new Scanner(System.in);
//System.out.println("请输入一个整数");
if (sc.hasNextInt()) {
num = sc.nextInt();
break;
} else {
System.out.println("你输入的类型不正确,请重新输入");
}
}
return num;
}
}
4. 常见对象之String类
就是由一个或多个字符组成的序列,字符串可以看成是字符数组,每一个字符从左往右编有索引,从0开始。
String类已经重写了父类的toString方法,打印的是字符串的字面值。已经重写过了父类的equals方法不再比较地址值是否相同,而是比较两个字符串的字面内容是否相同。
常见构造方法:
public String():空构造,初始化一个新创建的String对象,使其表示一个空字符序列。
package org.westos.demo;
public class MyTest {
public static void main(String[] args) {
String s = new String();
//String 类他重写了父类的toString方法,打印的是字符串字面值
System.out.println(s);
//"" 空串
System.out.println("");
System.out.println("=====================================");
String s1 = new String("abc");
System.out.println(s1);
}
}
public String(byte[] bytes):把字节数组转成字符串
public String(byte[] bytes,int index,int length):把字节数组的一部分转成字符串(index:表示的是从第几个索引开始, length表示的是长度)
package org.westos.demo;
public class MyTest2 {
public static void main(String[] args) {
// public String( byte[] bytes):把字节数组转成字符串
byte[] bytes = {97, 98, 99, 100, -28, -67, -96};
String s = new String(bytes);
System.out.println(s); // abcd你
//把字节数组的一部分转换成字节 0 起始索引 4表示转换4个字节
String s1 = new String(bytes, 0, 4);
System.out.println(s1); // abcd
// StringIndexOutOfBoundsException 字符串索引越界
String s2 = new String(bytes, 4, 3);
System.out.println(s2);// 你
}
}
public String(char[] value):把字符数组转成字符串
public String(char[] value,int index,int count):把字符数组的一部分转成字符串
package org.westos.demo2;
public class MyTest {
public static void main(String[] args) {
char[] chars={'a','b','c','d','你','好'};
//把字符数组转换成字符串。"abcd你好"
String s = new String();
for (int i = 0; i < chars.length; i++) {
s+=chars[i];
}
System.out.println(s); //abcd你好
System.out.println("=================================");
//把一个字符数组转换成字符串
String s1 = new String(chars);
System.out.println(s1); //abcd你好
//把字符数组的一部分转换成字符串,4 表示起始索引 2 转换2个字符
String s2 = new String(chars, 4, 2);
System.out.println(s2); //你好
}
}
public String(String original):把字符串常量值转成字符串
注意:
a.Java程序中所有字符串字面值都作为此类的实例实现,字符串字面值都是一个对象,可以调用方法
b.字符串是常量,他的值在创建之后不能更改,但是可以更改引用
理解:因为字符串的值是在堆内存的常量池中划分空间 分配地址值的,当我们采用字面值赋值的方式定义一个字符串的时候,他会先去字符串常量池,查找有没有该字符串,如果没有就构建一个新的字符串,如果有就把这个字符串的地址值直接赋给栈内存这个。
字符串中提供的方法:
A:判断功能
字符串A.equals(字符串B):判断两个字符串字面上内容是否相同,区分大小写;忽略大小写字符串A.equalsIgnoreCase(字符串B)
str.isEmpty():判断字符串是空串,或者看长度是否为零str.length()==0
判断字符串是否以某字符为开头:字符串A.startsWith(字符串A包含的片段)
判断字符串是否以某字符为结尾头:字符串A.endsWith(字符串A包含的片段)
判断字符串是否包含某个字符串:字符串A.contains(字符串A包含的片段)
例题:模拟登陆
package org.westos.demo4;
import java.util.Scanner;
public class MyTest5 {
public static void main(String[] args) {
/* A:
案例演示:
需求:模拟登录, 给三次机会, 并提示还有几次。
*/
String name = "zhangsan";
String password = "123456";
Scanner sc = new Scanner(System.in);
for (int i = 1; i <= 3; i++) {
System.out.println("请输入你的用户名");
String uname = sc.nextLine();
System.out.println("请输入密码");
String pwd = sc.nextLine();
if (uname.equals(name) && pwd.equals(password)) {
System.out.println("登录成功");
break;
} else {
if((3 - i)>0){
System.out.println("用户名或密码错误 你还剩余" + (3 - i) + "次机会");
}else{
System.out.println("你的次数用完,银行卡已被回收");
}
}
}
}
}
例:遍历字符串
package org.westos.demo5;
public class MyTest2 {
public static void main(String[] args) {
String str="往后余生,洗衣是你,做饭是你,带娃也是你";
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
System.out.println(c);
}
System.out.println("===========================");
// 倒叙
for (int length = str.length()-1; length >= 0; length--) {
char c = str.charAt(length);
System.out.println(c);
}
}
}
B:有关获取的方法
str.length() 获取字符串长度
str.charAt(2) 根据索引(2) 获取字符串中的单个字符
str.indexOf(“开”) 返回指定字符在字符串中第一次出现的索引,如果返回-1,表示没有找到
str.indexOf(“开”,2指定索引) 从指定的索引(2)处开始查找该字符第一次出现的索引,从后往前找 str.lastIndexOf(“开”)
截取一段字符串出来:str.substring(3),从指定索引处截取到末尾返回
str.substring(0,4) :0–起始位置,4-终止位置 根据起始索引和终止索引截取一部分字符串,是含尾不含头
例:统计一个字符串中大写字母、小写字母、数字字符出现的次数
package org.westos.demo5;
public class MyTest3 {
public static void main(String[] args) {
String str="asdfASFAEZSf5244dsfsdf555asdfa36425444asdfasdf";
int xiao=0;
int da=0;
int num=0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(ch>='a'&&ch<='z'){
xiao++;
}else if(ch >= 'A' && ch <= 'Z'){
da++;
}else{
num++;
}
}
System.out.println("小写字符有"+xiao+"个");
System.out.println("大写字符有" + da + "个");
System.out.println("数字字符有" + num + "个");
}
}
C:转换功能:
str.getBytes(): 把字符串转换为字节数组
str.toCharArray(): 把字符串转换为字符数组
String.valueOf(某一类型数据): 把很多种类型转换字符串
注意:String类的valueOf方法可以把任意类型的数据转成字符串
字符串.toLowerCase(): 把字符串转成小写
字符串.toUpperCase(): 把字符串转成大写
字符串A.concat(字符串B): 把字符串拼接,可以链式连用
练习:把一串字符 首字母变成大写,其余小写
package org.westos.demo6;
public class MyTest2 {
public static void main(String[] args) {
/* A:
案例演示:
需求:把一个字符串的首字母转成大写,其余为小写。(只考虑英文大小写字母字符)*/
String STR="aasdfaFDFDwefsdfaaaasdfasdf";
String s1 = STR.toLowerCase();
String s2 = s1.substring(0, 1).toUpperCase().concat(s1.substring(1).toLowerCase());
System.out.println(s2);
String str="aasdfaFDFDwefsdfaaaasdfasdf";
String s = str.substring(0, 1).toUpperCase().concat(str.substring(1).toLowerCase());
System.out.println(s);
/*
String first = str.substring(0, 1);
String s = first.toUpperCase();
String end = str.substring(1);
String s1 = end.toLowerCase();
String concat = s.concat(s1);
System.out.println(concat);
*/
}
}
D:替换
旧字符串.replace(“要替换的字符/字符串”,“新字符/字符串”)
去两端空格:str.trim();
练习:
去除一个字符串的左端空格
去除一个字符串的中间空格
package org.westos.demo7;
public class MyTest {
public static void main(String[] args) {
String s = " 张 三 ";
String replace2 = s.replace(" ", "");
System.out.println("-----" + replace2 + "-------------");
//去除字符串的两端空格
String trim = s.trim();
System.out.println(trim);
//作业:
// String s = " 张 三 "; //去除字符串的左端空格。
int z = s.indexOf("张");//找到左端第一个非空格字符索引
String sub = s.substring(z);//从此处截取到末尾返回
System.out.println("---------" + sub + "---------");
// String s = " 张 三 "; //去除字符串的中间空格。
int x = s.indexOf("三");
String cg = s.substring(0, z+1).concat(s.substring(x, s.length()));
System.out.println(s+"---------");
System.out.println(cg+"---------");
}
}
E:比较两个字符串
"xxx".compareTo(“xxx”);
会对照ASCII 码表 从第一个字母进行减法运算 返回的就是这个减法的结果;如果前面几个字母一样会根据两个字符串的长度进行减法运算返回的就是这个减法的结果;如果连个字符串一摸一样 返回的就是0;
public int compareToIgnoreCase(String str) 跟上面一样,只是忽略大小写的比较。
例:
需求:把字符串反转
举例:键盘录入"abc"
反转结果:“cba”
package org.westos.demo7;
public class testA {
public static void main(String[] args) {
String str = "往后余生,洗衣是你,做饭是你,带娃也是你";
char CH;
char[] ch = str.toCharArray();//把字符串转换为字符数组
// ch[0]=ch[str.length()-1];
// 循环替换
for (int i = 0; i < str.length() / 2; i++) {
CH=ch[i];
ch[i]=ch[str.length()-1-i];
ch[str.length()-1-i]=CH;
}
// 循环打印
/*for (int j = 0; j < str.length(); j++) {
System.out.print(ch[j]);
}*/
// 或者转换成字符串
String s1 = new String(ch);
System.out.println(s1);
}
}
例:
需求:统计大串中小串出现的次数
举例: “woaijavawozhenaijavawozhendeaijavawozhendehenaijavaxinbuxinwoaijavagun” 中java出现了5次
统计大串中小串出现的次数
package org.westos.demo7;
import java.util.Scanner;
public class testB {
public static void main(String[] args) {
// 统计大串中小串出现的次数
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要查询的小串:");
String s = sc.nextLine();
String str = "woaijavawozhenaijavawozhendeaijavawozhendehenaijavaxinbuxinwoaijavagun";
String njv = str.replace(s, "");
System.out.println(njv);
int num=(str.length()-njv.length())/s.length();
System.out.println(s + "出现了" + num + "次");
}
}