java基础(3)

1.API(Application Programming Interface)

概述:API也就是应用程序编程接口,java API指的就是JDK中提高的各种功能的java类

2.Object类

概述:Object是类层次结构的根类,是每个类的超类,每个类在写的时候可以写=显示的写出继承自Objec,也可以不写

Object的成员方法

1.public int hashCode():返回该对象的哈希值,哈希值是根据哈希算法计算出来的一个值,这个值和地址值相关,但是不是实际地址值,不同的对象的哈希值也不一样

2.public final Class getClass:返回此Object的运行时类,返回的是Class类,这是一个用于描述字节码文件对象的类

Class的一个方法:public String getName():以Sting的形式返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称

3.public String toString():返回该对象的字符串表示,这个字符串表示对我们没有任何意义,所以,建议子类都重写这个toString方法,重写的规则就是把该类的所有成员变量值组成返回即可,可以利用Eclipse的自动生成toString方法来重写这个toString方法(右键->source),需要注意的是直接输出一个对象的名称,其实就是调用该对象的toString()方法

4.public boolean equals(Object obj):指示其他对象是否与这个对象“相等”,这个方法,默认比较的是地址值,比较地址值一般意义不大,所以我们要重写该方法,重写的规则一般是用来比较对象的成员变量值是否相同,Eclipse同样有自动生成equals的功能(右键->source)

5.protected void finalize():当垃圾回收器确定不存在该对象的更多引用时,由对象的垃圾回收器调用此方法,用于垃圾回收,但是什么时候用,我们不知道

6.protected void clone(): 创建并返回此对象的一个副本,我们同样需要重写该方法,重写该方法的时候直接通过super调用父类的clone方法即可,需要注意的是这里需要抛出异常CloneNotSupportedException(关于异常,后面会讲)和实现一个Cloneable接口,以指示Object.clone()方法可以合法地对该类实例进行按字段复制,这个接口是标记接口,告诉我们实现该接口的类就可以实现对象的复制了

实例代码:

//Student.java

public class Student implements Cloneable{
	private String name;
	private int age;
	
	public Student(){};
	public Student(String name, int age){
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	//重写Object的toString方法
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	@Override
	//重写父类的equals方法
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	//重写clone方法
	protected Object clone() throws CloneNotSupportedException{
		return super.clone();	
	}
}

//StudentText.java

public class StudentText {
	public static void main(String[] args) throws CloneNotSupportedException {
		
		Student s1 = new Student("卢一", 19);
		//使用getClass方法得到该对象所对应的实体名称
		System.out.println(s1.getClass());//class cn.demo10.Student
		//打印对象其实是调用该对象的toString方法
		System.out.println(s1);//Student [name=卢一, age=19]
		Student s2 = new Student("卢一", 19);
		//使用了重写的equals方法,判断的其实他们的成员变量是否一样
		System.out.println(s1.equals(s2));//true
		//通过克隆方法克隆出来的对象是独立出来的,不会随着被克隆对象的改变而改变
		Object obj = s1.clone();
		Student s3 = (Student) obj;
		
		Student s4 = s1;
		System.out.println(s1.getName() + "---" + s1.getAge());//卢一---19
		System.out.println(s3.getName() + "---" + s3.getAge());//卢一---19
		System.out.println(s4.getName() + "---" + s4.getAge());//卢一---19
		
		System.out.println("===================");
		
		s4.setName("不是卢一");
		s4.setAge(20);
		
		System.out.println(s1.getName() + "---" + s1.getAge());//不是卢一---20
		System.out.println(s3.getName() + "---" + s3.getAge());//卢一---19
		System.out.println(s4.getName() + "---" + s4.getAge());//不是卢一---20
	}
}

3.Scanner类(java5之后有的)

概述:用于接受键盘录入数据

我们之前有说过,Scanner创建一个对象的格式为:

Scanner sc =new Scanner(System.in);

那么,它调用的是哪个构造方法呢?

它调用的是Scanner类下的Scanner(InputStream source)构造方法

这个传入的System.in,里面的System是一个类,这个类下有一个静态字段:public static final InputStream in,这是标准的输入流,对应着键盘输入,因此System.in是一个InputStream(这是一个类)类型

Scanner类的两个常用成员方法:

1.public boolean hasNextXxx():判断是否有某种类型的元素,如public boolean hasNextInt()

2.public Xxx nextXxx():获取该元素,如public int nextInt()

这两个方法可以配套使用:

import java.util.Scanner;

public class Demo4 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入一个整数:");
		if(sc.hasNextInt()){
			int num = sc.nextInt();//如果没有进行输入类型判断,则会报这个错误InputMismatchException
			System.out.println("num:" + num);
		}else{
			System.out.println("您输入的数据有误");
		}
	}
}

获取数据时的一个小问题:

先获取数值型数据,再获取一个字符串时,就会出现问题,这个问题的原因是程序把换行符号当作字符串赋给了第二个需要录入的值了

怎么解决:

  • 先获取一个数值,再创建一个新的键盘录入对象获取字符串
  • 把所有的数据都先按照字符串获取,然后要什么,你就对应转换为什么类型的数据

4.字符串(String类)

简单介绍

定义一个字符串的格式:String 变量名 = “xxx”

上面这样定义一个字符串,其实也是在定义一个String类型的对象,String就是类名称,字符串也是个对象

有人就说了,既然说字符串就是一个对象,他的类是谁呢?他为什么跟其他的对象不一样啊,他既不用导包,打印的时候也不是个地址值内容啊,接下来就来对上面的问题进行解释

解释:

1.对象肯定都有一个类与之对应,而字符串所对应的类就是String

2.所有的类都需要导包才能使用,除了两种情况

  • 要使用的目标类,和当前类位于一个包下
  • 要使用的目标类,位于java.lang包下,但是不包含子包(也就是说java.lang文件夹下的子文件夹里的类仍然需要导包才能用,而直接所属于java.lang文件夹的类就不需要导包即可使用)

3.打印println的方法逻辑:

  • 如果是字符串类型,那么直接显示内容
  • 如果不是字符串类型,那么就把他内部转换为字符串,然后再显示,而一般的对象都是使用“类型信息+@+地址值”作为字符串内容的

字符串创建的常见2+1种方式(两种构造方法,一种直接赋值)

1.常用的两个构造方法:

  • public String(char[] array):参数是一个字符串数组,根据字符串数组的内容来创建一个字符串
  • public String(char[] array, int offset, int count):根据字符数组的一部分内容来创建字符串,参数offset代表一个数组当中的起始索引,从0开始,参数count代表取用多少个字符

2.直接赋值

String str = "hello"

实例:

public class Demo8 {

	public static void main(String[] args) {
		//构造方法创建一个字符串
		char[] array = {'h', 'e', 'l', 'l', 'o'};
		String str1 = new String(array);
		System.out.println(str1);
		//构造方法创建一个字符串,只取部分字符来创建
		String str2 = new String(array, 2, 3);
		System.out.println(str2);
		//直接赋值的方法创建一个字符串
		String str3 = "hello";
		System.out.println(str3);

	}

}

字符串池(java7之前是在方法区中,java8之后是在堆内存):

字符串是最常用的对象,所以在程序中往往会出现很多个重复的字符串,为了节省内存,所以引入了“字符串池”的设计,可以重复利用字符串

关于字符串池的几点描述:

1.字符串池是位于堆内存当中的一小块空间,用来存放若干个字符串的地址值

2.字符串池当中绝对不会出现重复的字符串对应的地址,保证字符串不重复

3.凡是直接双引号赋值出来的字符串默认在字符串池中,而new出来的字符串默认不在池中

对第三点进行验证的代码:

public class Ddemo9 {

	public static void main(String[] args) { 
		String str1 = "hello";
		String str2 = "hello";
		
		char[] array = {'h', 'e', 'l', 'l', 'o'};
		String str3 = new String(array);
		String str4 = new String(array);
		// ==符号在基本数据类型中是判断数据内容是否相同,而在引用类型中是判断地址值是否相同
		System.out.println("str1 和str2是否是同一个地址值:" + (str1 == str2));//true
		System.out.println("str3 和str4是否是同一个地址值:" + (str3 == str4));//false
		System.out.println("str1 和str3是否是同一个地址值:" + (str1 == str3));//false
	}

}

注意:

字符串最容易给人误会的地方就是字符串创建后内容可以改变,其实,字符串对象在内存中一旦被创建,那么内容就不可以改变了,有人就说了,那我为啥可以改变变量str的值呢?其实,你改变的只是存放在栈内存里的str的指向的地址值,并没有改动在堆内存中的字符串,你给str重新赋一个新的值,其实是创建了一个新的字符串,并把str指向这个新的字符串的地址

字符串对象的常用成员方法:

1.字符串的比较方法:

a. public boolean equals(object obj):进行字符串的内容比较,严格区分大小写,参数obj就是另一个对象(跟谁比)

b. public boolean equalsIgnoreCase(String str):进行字符串的内容比较,但是忽略大小写

public class Demo10 {

	public static void main(String[] args) {
		char[] array = {'h', 'e', 'l', 'l', 'o'};
		String str1 = "hello";
		String str2 = new String(array);
		String str3 = "Hello";
		String str4 = null;
		// 进行字符串的地址比较
		System.out.println(str1 == str2);//false
		//进行字符串的内容比较,严格区分大小写
		System.out.println(str1.equals(str2));//true,等价于str2.equals(str1)
		System.out.println(str2.equals(str3));//false
		//进行字符串的内容比较,不区分大小写
		System.out.println(str2.equalsIgnoreCase(str3));//true
		//当字符串值为null时,无法调用字符串的方法,会抛出异常
		System.out.println(str4.equals("abc"));//抛出异常java.lang.NullPointerException
		//调换顺序后,就不会报错了,因此如果两个字符串比较中有一个是常量,那就把常量放在前面
		System.out.println("abc".equals(str4));//fasle
	}

}

2.字符串的替换方法

public String replace(CharSequence OldStr, CharSequence newStr):将字符串中出现的所有oldStr替换为newStr,参数类型CharSequence可以简单地认为就是字符串String,需要注意的是字符串的内容不会发生改变,所有replace方法的返回值是一个全新的字符串

public class Demo11 {

	public static void main(String[] args) {
		String str1 = "你真是个帅气的人儿";
		String str2 = str1.replace("帅气", "美丽");
		System.out.println("str1为 " + str1);//str1为 你真是个帅气的人儿
		System.out.println("str2为 " + str2);//str2为 你真是个美丽的人儿
	}

}

3.字符串的切割方法

public String[] split(String regex):将regex作为标记进行切刀,返回切分后的若干段字符串(字符串数组),现阶段强烈推荐不要使用英文句点作为分隔标记,因为英文句点在正则表达式中有特殊含义,而参数regex其实就是一个正则表达式,如果一定要使用,切割的标记应该使用“\\.”

public class Demo12{
	
	public static void main(String[] args){
		String str = "AAA,BBB,CCC";
		//根据“,”进行分割
		String[] strArray = str.split(",");
		for(int i = 0; i < strArray.length; i ++){
			System.out.println(strArray[i]);
		}
		
	}
	
}

字符串的成员方法总结

1.判断功能:

  • boolean equals(Object obj)
  • boolean equalsIgnoreCase(String str)
  • boolean contains(String str)
  • boolean startsWith(String str)
  • boolean endsWith(String str)
  • boolean isEmpty()

2.获取功能

  • int length()
  • char charAt(int index)
  • int indexOf(int ch)
  • int indexOf(String str)
  • int indexOf(int ch, int fromIndex)
  • int indexOf(String str, int fromIndex)
  • String substring(int start)
  • String substring(int start, int end)

3.转换功能

  • byte[] getBytes()
  • char[] toCharArray()
  • static String valueOf(char[] chs)
  • static String valueOf(int i)
  • String toLowerCase()
  • String toUpperCase()
  • String concat(String str)

4.其他功能

  • 替换功能
    • String replace(char old, char new)
    • String replace(String old, String new)
  • 去空格功能
    • STring trim()
  • 按字典比较功能
    • int compareTo(String str)
    • int compareToIgnoreCase(String str)

5.StringBuffer类

概述:我们如果进行字符串的拼接,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间,而StringBuffer就可以解决这个问题,通过StringBuffer创建出来的字符串是一个线程安全的可变字符串

StringBuffer与String的区别:

1.前者长度和内容可变,后者不可变

2.如果使用前者做字符串拼接,不会浪费太多的资源

StringBuffer的构造方法:

1.public StringBuffer():无参构造方法,默认分配16个字节的容量

2.public StringBuffer(int capacity):指定容量的字符串缓存区对象

3.public StringBuffer(String str):指定字符串缓冲区对象,它的容量会在这个str字符串长度的基础上加16

StringBuffer的成员方法

1.获取长度功能:

  • public int capacity():返回当前容量(理论值)

  • public int length():返回字符串长度(实际值)

2.添加功能:

  • public StringBuffer append(String str):可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身,这个方法可以调用多次,也可以链式调用多次,只能在末尾追加数据
  • public StringBuffer insert(int offset, String str):在指定位置把任意类型的数据插入到字符串缓冲区

3.删除功能

  • public StringBuffer deleteCharAt(int index):删除指定位置的字符,并返回本身
  • public StringBuffer delete(int start, int end):删除从指定位置开始到指定位置结束的内容(包左不包右),并返回本身

4.替换功能:

public StringBuffer replace(int start, int end, String str):从start到end用str替换

5.反转功能:

public StringBuffer reverse()

6.截取功能(注意这里返回的是一个String类型):

  • public String substring(int start)
  • public String substring(int start, int end)

String和StringBuffer的相互转换

String转换为StringBuffer:

  • 通过构造方法:StringBuffer sb = new StringBuffer("hello")
  • 通过append方法:StringBuffer sb = new StringBuffer();sb.append("hello").append("world")

StringBuffer转换为String:

  • 通过构造方法:String str = new String(buffer)
  • 通过toString方法:String str = buffer.toString()

示例代码:

public class Demo1 {
	public static void main(String[] args) {
		String s = "Hello";
		//将String型转换为StringBuffer类型
		StringBuffer sb = new StringBuffer(s);
		System.out.println(sb);
		//获取容量
		System.out.println(sb.capacity());
		//获取长度
		System.out.println(sb.length());
		//在末尾追加数据
		sb.append("world").append(true);
		System.out.println(sb);
		System.out.println(sb.capacity());
		System.out.println(sb.length());
		
		//在指定位置插入数据
		sb.insert(5, " ");
		sb.insert(11, " ");
		System.out.println(sb);
		//把字符串缓冲区类型转换为字符串类型
		StringBuffer buffer = new StringBuffer("aaa");
		String str1 = new String(buffer);
		//String str2 = buffer.toString();
		System.out.println(str1);
		
		//删除从指定位置开始到指定位置结束的字符
		sb.delete(11, sb.length());
		System.out.println(sb);
		//删除指定位置的字符
		sb.deleteCharAt(6);
		System.out.println(sb);
		//用指定内容替换指定位置的字符串
		sb.replace(6, 7, "w");
		System.out.println(sb);
		//反转功能
		sb.reverse();
		System.out.println(sb);
		//截取一小段字符串
		String str = sb.substring(6, sb.length());
		System.out.println(str);
		
	}
}

StringBuilder

StringBuilder是不同步的,数据不安全,效率高,在单线程情况下使用得比较多

使用:与StringBuffer的使用完全一样

面试题

1.String,StringBuffer,StringBuilder的区别?

答:String是内容不可变的,而后面两个都是内容可变的,StringBuffer是同步的,数据安全,StringBuilder是不同步的,数据不安全,效率高

2.StringBuffer和数组的区别?

答:二者都可以看作是一个容器,用来装其他数据;但是,StringBuffer的数据最终是一个字符串数据,而数组可以放置多种数据,但必须是同一种数据类型的

3.形式参数问题:

基本类型(还有String):形式参数的改变不影响实际参数

引用类型(除了String):形式参数的改变直接影响实际参数

6.数组高级(排序和查找)

排序算法:

1.冒泡排序:相邻元素两两比较,大的往后放,第一次完毕后,最大值就出现在了最大索引处,同理,继续,即可得到一个排好序的数组,第一次后,最后一个元素就不用再进行比较了,同理,一次一次的减少比较的元素,直到没有元素可进行比较即得到排好序的数组了,比较的次数为数组长度-1

代码实现:

public class Demo1 {
	public static void main(String[] args) {
		int[] array = {16, 80, 67, 30, 45};
		System.out.print("排序前:");
		printArray(array);
		System.out.print("排序后: ");
		bubbleSort(array);
		printArray(array);
	}
	public static void bubbleSort(int[] array){
		//这里的array.length - 1是比较次数
		for(int y = 0; y < array.length - 1; y ++){
			//这里的array.length - 1是为了防止索引越界,-y则是为了减去最后排好序的元素
			for(int x = 0; x < array.length - 1 - y; x ++){
				if(array[x] > array[x + 1]){
					int temp = array[x];
					array[x] = array[x + 1];
					array[x + 1] = temp;
				}
			}
		}
	}
	public static void printArray(int[] array){
		System.out.print("[");
		for(int i = 0; i < array.length; i ++){
			if(i == array.length - 1){
				System.out.print(array[i]);
			}else{
				System.out.print(array[i] + ",");
			}
		}
		System.out.println("]");
	}
}

2.选择排序:从索引0开始,一次和后面元素比较,小的往前放,第一次完毕后,最小值出现在了最小索引处,最后一次比较是数组长度-2的元素和数组长度-1的元素进行比较

实现代码:

public class Dem2 {
	public static void main(String[] args) {
		int[] array = {16, 80, 67, 30, 45};
		System.out.print("排序前:");
		printArray(array);
		System.out.print("排序后: ");
		selectSort(array);
		printArray(array);
	}
	
	public static void selectSort(int[] array){
		for(int y = 0; y < array.length - 1; y ++){
			for(int x = y + 1; x < array.length; x ++){
				if(array[x] < array[y]){
					int temp = array[y];
					array[y] = array[x];
					array[x] = temp;
				}
			}
		}
	}
	
	public static void printArray(int[] array){
		System.out.print("[");
		for(int i = 0; i < array.length; i ++){
			if(i == array.length - 1){
				System.out.print(array[i]);
			}else{
				System.out.print(array[i] + ",");
			}
		}
		System.out.println("]");
	}
}

查找

1.基本查找:数组元素无序(从头找到尾)

2.二分查找:数组元素有序(折半查找),每次都猜中间的那个元素,比较大或者小,就能减少一半的元素

实现二分查找的思路:

1.定义最小索引,最大索引

2.计算出中间索引

3.拿中间索引的值和要查找的元素进行比较,相等,就直接返回当前的中间索引,大了的话,在左边找,小了的话,在右边找

4.重写获得最小索引或者最大索引,回到第2个步骤,重复动作,直到获得要查找的元素

二分查找代码实现:

public class Demo3 {
	public static void main(String[] args) {
		int[] array = {11, 22, 33, 44, 55, 66, 77};
		System.out.println(getIndex(array, 33));
	}
	public static int getIndex(int[] array, int value){
		//定义最大索引和最小索引
		int max = array.length - 1;
		int min = 0;
		//计算出中间索引
		int mid = (max + min) / 2;
		//拿中间索引的值和要查找的值进行比较
		while(array[mid] != value){
			if(array[mid] > value){
				max = mid - 1;
			}else if(array[mid] < value){
				min = mid + 1;
			}
			//如果要查找的值不存在,就会返回-1
			if(min > max){
				return -1;
			}
			mid = (max + min) / 2;
		}
		
		return mid;
	}
}

Arrays类(java2后有)

前面说的排序和查找是比较常见的操作,那么,java有没有给我们提供好一个已经定好的方法呢?答案是有的,这些方法就在Arrays类中

Arrays类无构造方法,它的成员方法都是静态的

Array的静态方法:

1.public static String toString(int[] a):把数组转成字符串

2.public static void sort(int[] a):对数组进行排序,底层是用快速排序实现的

3.public static int binarySearch(int[] a, int key):二分查找

7.基本类型包装类

为了基本数据类型进行更多的操作,更方便的操作,java就针对每一种基本数据类型提供了对应的类类型,包装类类型

8个基本数据类型对应的8个包装类

byte-----Byte

short-----Short

int-----Integer

long-----Long

float-----Float

double-----Double

char-----Character

boolean-----Boolean

Integer类

构造方法:

1.public Integer(int value)

2.public Integer(String s)

成员变量:

MAX_VALUE:得到int类型的最大值(2147483647)

MIN_VALUE:得到int类型的最小值(-2147483648)

从int类型转换为String类型的方法:

1.String str = "" + 100;

2.String str = String.valueOf(100);

3.Integer i = new Integer(100);String str = i.toString()

4.public static String toString(100)

从String类型转换为int类型

1.Integer obj = new Integer("100");obj.intValue()

2.public static int parseInt(String s):重点关注,其他的包装类中也有对应的方法,如parseFloat等

十进制到其他进制的转换方法:

1.public static String toBinaryString(int i):转换为2进制的数

2.public static String toOctalString((int i):转换为8进制的数

3.public static String toHexString(int i):转换为16进制的数

4.public static String toString(int i, int radix):转换为指定进制的数,指定的进制从(2到36进制)

其他进制到十进制的转换方法:

public static int parseInt(String s, int radix):第一个数是字符串,第二个数是这个字符串所表示的进制

自动装箱拆箱(java5之后才有):

自动装箱(把基本类型转换为包装类型):Integer num1 = 12;

自动拆箱(把包装类型转换为基本类型):System.out.println(num1 + 11);

需要注意的是在使用时,Integer x = null;代码就会出现NullPointerException异常,建议先判断是否为null,再使用

缓存池:Integer的数据直接赋值(内部走的就是Integer的valueOf方法),如果数值在-128到127之间,会之间从缓冲池里获取数据

代码证明缓存池的存在(看Integer的valueOf方法的源码也可以知道):

public class Demo7 {
	public static void main(String[] args) {
		/*Integer对象的数字在一个字节之内(-128-127)之间,那么它会把数据缓存到缓存池里面,
		如果下一次有人有使用到这个数字,那么就直接从缓存池里取,
		因此在一个字节范围内的基本类型对象同一个内容值用的是同一个地址值*/
		
		Integer num1 = 12;
		Integer num2 = 12;
		System.out.println(num1 == num2);//true
		
		Integer num3 = 129;
		Integer num4 = 129;
		System.out.println(num3 == num4);//false
		
		Integer num5 = Integer.valueOf(12);
		Integer num6 = Integer.valueOf(12);
		System.out.println(num5 == num6);//true
		
	}
}

8.Character

概述:Character类在对象中包装一个基本类型char的值,此外,该类还提供了几种方法,以确定字符的类别(小写字母,数组,等等),并将字符从大写转换到小写,反之亦然

构造方法:Character(char value)

Character的静态方法们:

1.public static boolean isUpperCase(char ch):判断给定的字符是否是小写

2.public static boolean isLowerCase(char ch):判断给定的字符是否是大写

3.public static boolean isDigit(char ch):判断给定的字符是否是数字字符

4.public static char toUpperCase(char ch):把给定的字符转换为大写字符

5.public static char toLowerCase(char ch):把给定的字符转换为小写字符

案例代码(统计字符串中大小写字母及数字出现的次数)

public class Demo1 {
	public static void main(String[] args) {
		int bigCount = 0;
		int smallCount = 0;
		int digitCount = 0;
		
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入:");
		String str = sc.nextLine();
		
		char[] chs = str.toCharArray();
		
		for(int i = 0; i < chs.length; i ++){
			if(Character.isUpperCase(chs[i])){
				bigCount ++;
			}else if(Character.isLowerCase(chs[i])){
				smallCount ++;
			}else if(Character.isDigit(chs[i])){
				digitCount ++;
			}
		}
		
		System.out.println("大写字母有" + bigCount + "个");
		System.out.println("小写字母有" + smallCount + "个");
		System.out.println("数字字符有" + digitCount + "个");
	}
}

9.正则表达式

概述:符合一定规则的字符串,规则字符在java.util.regex.Pattern类中定义

正则表达式的组成规则:

1.字符:

  • x字符代表x字符,如‘a’就代表字符a
  • \:反斜线字符
  • \n:换行符(‘/u000A’)
  • \r:回车符(‘/u000D’)

2.字符类

  • [abc]:a,b或者c
  • [^abc]:任何字符,除了abc
  • [a-zA-Z]:a到z或者A到Z,两头的字母包括在内
  • [0-9]:0到9的字符都包括

3.预定义字符类

  • . :任何字符,如果就要.本身,就得用.表示
  • \d:数字[0-9]
  • \w:单词字符[a-zA-Z0-9]

4.边界匹配器

  • ^:行的开头
  • $:行的结尾
  • \b:单词边界:就是不是单词字符的地方(如“hello world,java”这里的空格和逗号就是单词边界)

5.数量词

  • x? :x出现一次或一次也没有
  • x* :x出现0此或多次
  • x+ :x出现一次或多次
  • x{n}:x恰好要n次
  • x{n, }:x至少n次
  • x{n, m}:x至少n次,但是不超过m次

正则表达式的应用

1.判断功能:String类的public boolean matches(String regex)

实例代码(判断是否匹配邮箱成功):

import java.util.Scanner;

public class Demo1 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入你的邮箱");
		String email = sc.nextLine();
		
		//以下正则表达式等价于"[a-zA-Z_0-9]+@[a-zA-Z_0-9{2,6}(\\.[a-zA-Z_0-9]]{2,3})+"
		String regex = "\\w+@\\w{2,6}(\\.\\w{2,3})+";
		boolean flag = email.matches(regex);
		
		System.out.println("flag: " + flag);
	}
}

2.切割功能:

String类的public String[] split(String regex)

实例代码(把路径切割成一个个的子路径):

public class Demo2 {
	public static void main(String[] args) {
		//硬盘上的路径,我们应该用\\替代\
		String str = "C:\\Users\\luyi\\luyi\\Desktop\\java学习笔记";
		//两个\才能代表一个\,所以我们需要四个\
		String[] stringArray = str.split("\\\\");
		for(int i = 0; i < stringArray.length; i ++){
			System.out.println(stringArray[i]);
		}
	}
}

3.替换功能

String类的public String replaceAll(String regex, String replacement)

示例代码(去除所有数字):

public class Demo3 {
	public static void main(String[] args) {
		String str = "122hello 23290world";
		
		String regex = "\\d+";
		String str2 = str.replaceAll(regex, "*");
		System.out.println(str2);
	}
}

4.获取功能

Pattern类和Matcher类的合作使用:

示例代码(挑出字符串里面有3个字符的字符串):

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Demo4 {
	public static void main(String[] args) {
		String str = "jin tian da jia you hao hao xue xi ma";
		//规则
		String regex = "\\b\\w{3}\\b";
		
		//把规则编译成模式对象
		Pattern p = Pattern.compile(regex);
		//通过模式对象得到匹配器对象
		Matcher m = p.matcher(str);
		//调用匹配器对象的功能
		while(m.find()){
			//注意:一定要先find(),然后才能调用group()
			System.out.println(m.group());
		}
	}
}

10.Math类

前面我们有简单提到过Math的random()方法,下面对它进行详细的介绍

成员变量:

public static final double PI:最接近pi的值

public static final double E: 最接近e(自然对数的底数)的值

成员方法:

1.public static int abs(int a):绝对值

2.public static double ceil(double a):向上取整

3.public static double floor(double a):向下取整

4.public static int max(int a, int b):得到两个数之中的最大值(min类似),如果想要比较三个数的最大值,可以使用max方法的嵌套调用来实现,如 Math.max(Math.max(12, 34), 56)

5.public static double pow(double a, double):得到a的b次幂

6.public static double random():随机数[0.0, 1.0)

7.public static int round(float a):四舍五入得到整数(还有个参数为double的类似方法)

8.public static double sqrt(double a):得到正平方根

案例(获取任意范围内的随机数):

import java.util.Scanner;

public class RandomText {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入随机数的开始值");
		int start = sc.nextInt();
		System.out.println("请输入随机数的结束数");
		int end = sc.nextInt();	
		
		System.out.println("随机数: " + getRandom(start, end));
	}
	public static int getRandom(int start, int end){
		//+1是为了确保随机数的结束数也能被取到
		int number = (int)(Math.random() * (end - start + 1)) + start;
		return number;
	}
}

11.Random类

概述:产生随机数的类

构造方法:

1.public Random():没有给种子,用的是默认种子,是当前时间的毫秒值

2.public Random(long send):给出指定的种子

给定种子后,每次得到的随机数是相同的

成员方法:

1.public int nextInt():返回的是int范围内的随机数

2.public int nextInt(int n):返回的是[0, n)范围的随机数

12.System类

概述:包含一些有用的类字段和方法,他不能被实例化

System的一些方法:

1.public static void gc():可用于垃圾回收,在执行System.gc()之前,系统会自动调用finalize()方法清楚对象占有的资源,通过super.finalize()方式可以实现从下到上的finalize()方法的调用,即先释放自己的资源,再去释放父类的资源,但是,不要在程序中频繁调用垃圾回收,因为每一次执行垃圾回收,jvm都会强制启动垃圾回收器运行,这会耗费更多的系统资源,只有在执行大量的对象的释放时,再调用垃圾回收最好

2.public static void exit(int status):终止当前运行的java虚拟机,参数用做状态码,根据惯例,非0的状态码表示异常终止

3.public static long currentTimeMillis():返回以毫秒为单位的当前时间,可用于测程序的运行时间

4.public static void arraycopy(Object src, int srcPos,Object dest, int destPos, int length):表示从src源数组中的srcPos起始位置复制length个元素到目标数组dest(从目标数组的destPos位置开始粘贴进去)

13.BigInteger类

概述:可以让超过Integer范围内的数据进行运算

构造方法:public BigInteger(String val)

成员方法:

1.public BigInteger add(BigInteger val):加运算

2.public BigInteger subtract(BingInteger val):减运算

3.public BigInteger multiply(BigInteger val):乘运算

4.public BigInteger divide(BigInteger val):除运算

5.public BigInteger[] divideAndRemainder(BigInteger val):返回有商和余数的数组

14.BigDecimal类

在介绍BigDecimal类之前,我们先来看看一个案例

public class BigDecimalDemo {
	public static void main(String[] args) {
		System.out.println(0.09 + 0.01);//0.09999999999999999
		System.out.println(1.0 -  0.32);//0.6799999999999999
		System.out.println(1.015 * 100);//101.49999999999999
		System.out.println(1.301 / 100);//0.013009999999999999
	}
}

从上面的例子我们可以看到,float和double类型的数进行加减乘除并没有得到我们想要的数据,而是得到一个无限接近我们想要的数据的数据,这就是为什么我们需要BigDecimal类的原因了

概述:由于在运算的时候,float和double很容易丢失精度,所以,为了能精确的表示、计算浮点数,java提供了BigDecimal

构造方法:public BigDecimal(String str)

成员方法:

1.public BigDecimal add(BigDecimal augend):加运算

2.public BigDecimal subtract(BigDecimal subtrahend):减运算

3.public BigDecimal mutiply(BigDecimal mutiplicand):乘运算

4.public BigDecimal divide(BigDecimal divisor):除运算

5.public BigDecimal divide(BigDecimal divisor, int scale, int roundingMole):除运算求得的商有scale位小数(第三个参数表示按某个东西进行舍取)

15.Date类

概述:类Date表示特定的时间,精确到毫秒

构造方法:

1.Date()

2.Date(long date):根据毫秒值创建日期对象

成员方法:

1.public long getTime():获取时间,以毫秒位单位

2.public void setTime(long time):设置时间

16.DateFormat类和SimpleDateFormat类

概述:可以进行日期和字符串的格式化(日期转换为字符串)和解析(字符串转换为日期),但是由于是抽象类,所以使用具体子类SimpleDateFormat

SimpleDateFormat的构造方法:

1.SimpleDateFormat():默认模式

2.SimpleDateFormat(String pattern):给定的模式

这个模式的字符串怎么写呢?

年 y

月 M

日 d

时 H

分 m

秒 s

如yyyy-MM-dd HH:mm:ss表示像2020-7-22 00:25:20 的时间

Date的成员方法(都需要通过SimpleDateFormat类来实现):

1.public final String format(Date date):把日期格式化为指定模式的字符串

2.public Date parse(String source):把字符串解析为日期

示例代码:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo {
	public static void main(String[] args) throws ParseException {
		Date d1 = new Date();
		System.out.println("d1:" + d1);//d1:Wed Jul 22 00:36:30 CST 2020
		
		SimpleDateFormat sdf1 = new SimpleDateFormat();
		System.out.println(sdf1.format(d1));//20-7-22 上午12:36
		
		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sdf2.format(d1));//2020-07-22 00:36:30
		
		String str = "2020-07-22 00:35:10";
		//注意这里格式必须和给定的字符串格式匹配
		SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sdf3.parse(str));//Wed Jul 22 00:36:30 CST 2020
	}
}

17.Calendar类

概述:Calendar类是一个抽象类,它为特定瞬间与一组诸如YEAR,MONTH,DAY_OF_MONTH,,HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法

成员变量:

  • Calendar.YEAR:当前的年份
  • Calendar.MONTH:当前的月份
  • Calendar.DATE:当前的日期
  • ...

成员方法:

1.public static Calendar getInstance():获取子类对象

2.public int get(int field):获得给定的日历字段对应的时间,如获取当前年份

3.public void add(int field, int amount):根据给定的日历字段和对应的时间,来对当前的日历进行操作

4.public final void set(int year, int month, int date):设置当前日历的年月日

5.public long getTimeInMillis():获取毫秒值

案例(获取任意年份的2月份有多少天):

import java.util.Calendar;
import java.util.Scanner;

public class CalendarText {
	public static void main(String[] args) {
		//键盘录入年份
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入任意年份");
		int year = sc.nextInt();
		//获取Calendar的子类对象
		Calendar c = Calendar.getInstance();
		//设置日历对象的年月日
		c.set(year, 2, 1);
		//在设定好的3月1号往前推一天就可以得到2月有几天了
		c.add(Calendar.DATE, -1);
		
		System.out.println("这一年的2月有" + c.get(Calendar.DATE) + "天");
	}
}
posted @ 2020-07-25 15:19  luyi001  阅读(215)  评论(0编辑  收藏  举报