【JavaSE】day02_正则表达式 、 Object 、 包装类
1.正则表达式
所谓正则表达式就是使用一系列预定义的特殊字符来描述一个字符串的格式规则,然后使用该格式规则匹配某个字符串是否符合格式要求。
1)“.”和"\"
"."点儿,在正则表达式中表示任意一个字符。
"\"在正则表达式中是转意字符,当我们需要描述一个已经被正则表达式使用的特殊字符时,我们就可以通过使用"\"将其转变为原本的意思。
\d | 表示任意一个数字 |
\w | 表示任意一个单词字符(只能是 数字,字母,下划线) |
\s | 表示任意一个空白字符(\t \r \n \f \x0B) |
\D | 表示任意一个非数字字符 |
\W | 表示任意一个非单词字符 |
\S | 表示任意一个非空白字符 |
2)字符集合 []
"[]"用来描述单一字符,方括号内部可以定义这个字符的内容,也可以描述一个范围。
例如:
[abc]:表示该字符只能是a或者b或者c
[123]:表示该字符只能是1或者2或者3
当我们需要描述所有小写字母时,我们可以使用范围 [a-z],表示该字符可以是任意一个小写字母。
同样还可以使用 [0-9] 来表示该字符可以是任意一个数字。
也可以在多个范围内选择。比如,[a-zA-Z0-9_] 表示该字符可以是任意字母,数字以及"下划线"(=\w)。
3)"*"、"+"、"?"
* | 表示内容出现0-若干次 |
+ | 表示内容可以连续出现至少1次以上 |
? | 表示内容出现0-1次 |
4、{n}、{n,}、{n,m}
{n} | 表示内容必须出现n次 |
{n,} | 表示内容出现至少n次 |
{n,m} | 表示内容出现n-m次 |
例如,\d{11} 就表示数字只能出现11位.
5)分组 “()”
() 可以将内容看做一个整体,()中可以使用"|"来表示或关系。
例如,(+86|0086) 表示这里可以是+86或者0086。
6)"^"和"$"
通过在正则表达式的开始添加"^"以及末尾添加"$"来表示一个整体。若不使用它们,那么正则表达式只匹配某个字符串的部分内容是否符合格式规则,但使用它们,则要求字符串必须从头到尾都满足该格式规则。
例如,^\w{ 8,10 }$ 表示整体字符串只能出现单词字符8-10个
注:在java中,写不写"^"和"$",都是完全匹配,都相当于写"^"和"$"。
2. String正则相关API
1) matches方法
matches()方法的参数要求我们传入一个用字符串描述的正则表达式,然后使用该正则表达式描述的字符串格式规则来匹配当前字符串,若满足那么该方法返回true。否则返回false。
例如:
<span style="font-size:18px;"><span style="font-size:18px;">package day02;
/**
* boolean matches(String regex)
* 验证当前字符串是否满足给定的正则表达式的格式要求
* 需要注意:无论正则表达式是否使用类"^","$"都是全匹配验证
*
*/
public class MatchesDemo {
public static void main(String[] args) {
String str = "fancq@tarean.com.cn";
/*
* [a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-z]+)+
* \w+@\w+(\.[a-z]+)+
*/
String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\\.[a-z]+)+";
boolean matches = str.matches(regex);
System.out.println(matches);
}
}
</span></span>
2)split方法
String[] split(String regex):参数要求传入一个用字符串描述的正则表达式,然后使用该正则表达式描述的字符串规则来匹配当前字符串,并按照满足的部分将字符串拆分。
例如:
<span style="font-size:18px;"><span style="font-size:18px;">package day02;
import java.util.Arrays;
/**
* String split(String regex)
* 将当前字符串中满足正则表达式的部分“切掉”,
* 保留剩下部分,拆分字符串操作。
*
*/
public class SplitDemo {
public static void main(String[] args) {
String str = "ashf23raekj239qsdj8t4xdsf84a";
String[] array = str.split("[0-9]+");
System.out.println(Arrays.toString(array));
//[ashf, raekj, qsdj, t, xdsf, a]
array = str.split("[0-9]");
System.out.println(Arrays.toString(array)); //可以切出空串
//[ashf, , raekj, , , qsdj, t, xdsf, , a]
}
}
</span></span>
3)replaceAll方法
String replaceAll(String regex,String replacement):参数要求传入一个用字符串描述的正则表达式和一个需要替换的字符串,然后使用该正则表达式描述的字符串规则来匹配当前字符串,并将满足的部分替换为需要替换的这个字符串。
例如:
<span style="font-size:18px;"><span style="font-size:18px;">package day02;
/**
* String replaceAll(String regex,String replacement)
* 将字符串中匹配正则表达式regex的部分替换成replacement
*
*/
public class ReplaceAllDemo {
public static void main(String[] args) {
String str = "21dasf234sszf";
/*
* 将当前字符串中的数字部分,替换为"***"
*/
str = str.replaceAll("\\d+","***");
System.out.println(str);
}
}
</span></span>
3. Object
1)Object类是java中所有类的顶级父类。若我们定义的一个类没有显式的使用extends继承某个类时,默认就是继承自Object的。
2)toString()方法
String toString(){}
该方法java希望我们重写时返回一个字符串,这个字符串的原则为:用一个字符串来描述当前对象。
Object实现了toString()方法,返回的是当前对象的“句柄”。
格式为:类的完全限定名@hashcode。
因为Object实现的toString()方法不具备什么实际开发意义,所以若我们需要在子类中使用该方法时通常我们会重写它。
demo:
<span style="font-size:18px;"><span style="font-size:18px;">package day02;
import java.util.Arrays;
/**
* 图片重命名
*
*/
public class StringDemo01 {
public static void main(String[] args) {
String imgName= "daadga.png";
String[] arr = imgName.split("\\.");
System.out.println(Arrays.toString(arr));
imgName = System.currentTimeMillis()+"."+arr[arr.length-1]; //系统时间
System.out.println(imgName);
}
}
</span></span>
3)String类重写toString()
public String toString(){
return this;
}
从源码中我们可以看到,String重写了Object的toString()方法,该方法直接将当前字符串对象自身返回。
4)equals()方法
boolean equals(){}
该方法java希望我们重写时返回一个boolean值,表示两个对象间的内容比较是否一致。
Object已经实现了该方法,代码如下:
public boolean equals (Object obj) {
return (this == obj);
}
由此看出,实际上Object中重写该方法依旧使用"=="比较,所以当我们在子类中需要比较对象内容时就要重写该方法。
5)如何重写equals方法
重写equals方法应遵循几个规则:
任何对象与null比较都应返回false
两个对象不属于同一个类时应返回false
同一个对象equals比较应当恒等为true
那么除此之外,两个对象在比较时,应根据具体的业务需求来自行决定对象的哪些属性相同时对象内容相同。
6)String重写equals()方法
String重写了equals方法,作用是比较两个字符串对象中保存的字符序列是否完全一致。
7)equals与 == 的区别
"=="是值比较,对于引用类型变量而言,该变量保存的是对象的地址,所以使用"=="比较时,意思为两个变量的地址是否相等,换句话说就是看两个变量引用的是否为同一个对象
equals是内容比较,对于两个引用变量而言,是比较两个变量所引用的对象内容是否相同。
举个例子, 就好像一对双胞胎,他们是两个独立的个体,是两个对象。所以那么用"=="比较是 false。但是因为他们“长得一样”,所以equals方法比较是true。
我们也可以变相的理解为:"=="是判断是否为同一个,而"equals"是判断像不像。
代码演示:
<span style="font-size:18px;"><span style="font-size:18px;">package day02;
/**
* 该类用于表示一个直角坐标系上的点
* 这里使用该类练习重写Object相关方法使用
*
*/
public class Point {
private int x;
private int y;
public Point(){
}
public Point(int x,int y){
this.x = x;
this.y = y;
}
/**
* 重写toString方法
* 当我们需要使用当前类的toString方法时,通常我们就需要
* 重写该方法。具体返回字符串的格式没有严格要求。可根据
* 将来实际开发中的需求而定。但通常返回的字符串中应包含
* 当前类的属性值。以便了解当前对象的信息。
*/
public String toString(){
return "("+x+","+y+")";
}
/**
* 通常我们会重写一个类的equals方法。
* equals方法的作用是比较当前对象与给定对象的内容是否一样(属性)。
* 若不重写则使用Object提供的,其内部就算用“==”实现的,所以无意义。
* equals方法在比较两个对象内容一致时不一定要求所有属性值都一样,
* 这就根据实际需求而定。
*/
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(obj==this){
return true;
}
if(obj instanceof Point){
Point p = (Point)obj;
return this.x==p.x && this.y==p.y;
}
return false;
}
public static void main(String[] args) {
//Object
Point p = new Point(1,2);
Point p1 = new Point(1,2);
System.out.println(p==p1);
/*
* 不重写equals的话,调的是Object的equals方法
* “==”
*/
System.out.println(p.equals(p1));
//System.out.println(p.equals(p));
/*
* 若我们不重写Point从Object那继承的toString方法时,
* 使用的就是Object提供的,它定义的该方法格式:类名@地址
* 通常没有什么意义。
*/
String str = p.toString();
System.out.println(str); //(1,2)
/*
* System.out.println(Object o)
* 该方法会将给定的对象的toString方法返回的
* 字符串以行为单位输出到控制台。
*/
System.out.println(p); //(1,2)
}
}
</span></span>
4. 包装类
1)包装类概述
我们知道java是面向对象的语言,其精髓之一是可以使用多态性,提高程序的灵活度。但是java中有8个基本类型:byte,short,int,long,float,double,char,boolean。它们是以值的形式存在于内存中,而不是对象。它们不是Object的子类,不能参与面向对象的开发。在java1.5版本以前以下的代码是不能通过的:
<span style="font-size:18px;"><span style="font-size:18px;">public class Test{
public static void main(String[] args){
String str = "hello";
doSome(str);//可以,因为String是Object的子类
int i = 1;
//程序编译不通过,原因在于int不是Object的子类,不能使用多态性。
doSome(i);
}
public static void doSome(Object o){
....
}
}</span></span>
问题出现的原因就是基本类型int没有继承关系,它不是Object的子类。所以,若想让基本类型以对象的形式存在,我们就需要定义一个类Integer,然后用其实例来描述一个基本类型int。这样的好处在于,我们使用对象来描述基本类型数据,而类又是继承自Object的。从而可以让基本类型参与面向对象的开发。好在,像Integer这样的类不需要我们定义,因为java已经提供了8中基本类型对应的包装类。
对于8个基本类型,java提供了他们相应的包装类:
基本类型 | 包装类 | 父类 |
byte | java.lang.Byte | java.lang.Number |
short | java.lang.Short | java.lang.Number |
int | java.lang.Integer | java.lang.Number |
long | java.lang.Long | java.lang.Number |
float | java.lang.Float | java.lang.Number |
double | java.lang.Double | java.lang.Number |
char | java.lang.Character | java.lang.Object |
boolean | java.lang.Boolean | java.lang.Object |
2)java.lang.Number
Number是一个抽象类。本身不能实例化。Number 的子类必须提供将表示的数值转换为 byte、double、float、int、long 和 short 的方法
比如:
abstract double doubleValue() 以double形式返回指定的数值
abstract int intValue() 以int形式返回指定的数值
abstract float floatValue() 以float形式返回指定的数值
3)包装类的使用
<span style="font-size:18px;">package day02;
/**
* 包装类
* 由于java中有8个基本类型,他们不是以对象的形式存在,
* 没有面向对象的特征,所以不能参与面向对象的开发,为了
* 解决这个问题,java针对他们定义类8个包装类。
* 其中6个是表示数字的,他们都继承自Number。
*
*/
public class IntegerDemo01 {
public static void main(String[] args) {
//将int转换为包装类Integer
Integer i = new Integer(123);
System.out.println(i); //123
//包装类转换成基本类型
int ii = i.intValue();
//也可以转换成其他基本类型的数字,但不常用
long l = i.longValue();
double d = i.doubleValue();
System.out.println(d); //123.0
/*
* 基本类型转换成包装类更常用的方法不是直接new对象,
* 而是使用包装类的静态方法valueOf
*
*/
Integer i1 = Integer.valueOf(123);
System.out.println(i1);
/*
* 使用Integer.valueOf创建包装类对象时,当在-128~127时,
* 会重用对象,减少内存开销。
*/
Integer i2 = Integer.valueOf(123);
System.out.println(i1==i2); //true
Double b1 = Double.valueOf(123);
Double b2 = Double.valueOf(123);
System.out.println(b1==b2); //false
Integer i3 = 45;
Integer i4 = 45;
System.out.println(i3==i4);
}
}
</span>
4)MAX_VALUE MIN_VALUE
<span style="font-size:18px;">package day02;
/**
* 数字类型的包装类都支持两个常量
* MAX_VALUE MIN_VALUE
* 分别用来表示其对应的基本类型的取值范围。
*
*/
public class IntegerDemo02 {
public static void main(String[] args) {
int intMax = Integer.MAX_VALUE;
long longMax = Long.MAX_VALUE;
short shortMax = Short.MAX_VALUE;
double doubleMax = Double.MAX_VALUE;
System.out.println("intMax:"+intMax);
System.out.println("longMax:"+longMax);
System.out.println("shortMax:"+shortMax);
System.out.println("doubleMax:"+doubleMax);
}
}
</span>
5)parseXXX(String str)
<span style="font-size:18px;">package day02;
/**
* 包装类提供了一个非常常用的静态方法
* parseXXX(String str)
* 可以将给定的字符串转换成包装类对应的基本类型值。
*
*/
public class IntegerDemo03 {
public static void main(String[] args) {
String str1 = "123";
int i = Integer.parseInt(str1);
System.out.println(i); //123
double d = Double.parseDouble(str1);
System.out.println(d); //123.0
/*
* 想要进行转换有一个要求,就是字符串中的所有字符
* 必须能正确表示要转换的数字,否则会抛出数字格式
* 异常。NumberFormatException
* 使用parseInt时,必须是严格意义上的整数
*/
String str2 = "123.123";
//int i2 = Integer.parseInt(str2);
//System.out.println(i2); //抛异常。如果注释掉转成int,则正确
double d2 = Double.parseDouble(str1);
System.out.println(d2); //123.0
}
}
</span>
6)自动装箱和拆箱操作
<span style="font-size:18px;">package day02;
public class IntegerDemo04 {
public static void main(String[] args) {
/*
* java1.5以后推出一个新的特性,自动拆装箱
* 当编译器在编译源程序时发现:
* 当我们需要一个基本类型,而实际给的是引用类型时,
* 会帮我们补全代码,将引用类型转换为基本类型(自动拆箱)。
* 所以下面的代码在编译后的class文件中的样子:
* int i = new Integer(1).intValue();
*/
int i = new Integer(1); //
/*
* 当我们需要引用类型,而实际给的是基本类型时,
* 会帮我们补全代码(自动拆箱)。
* 所以下面的代码在编译后的class文件中的样子:
* Integer ii = Integer.valueOf(123);
*/
Integer ii = 123; //
/*
* 所以,自动拆装箱是编译器认可的,不是JVM认可的。
*/
}
}
</span>