JAVA笔记总结(5000字)内含常用API(String,Runtime,Object等类的讲解)【建议收藏慢慢看!!!】
新人创作,不足之处还望大家多多指点~~
本文如有侵权,练习作者马上删!
常用工具类
Object类
来源:java. lang. Object
Object类是所有类的父类,类似于"万物之首",包括我们自己写的类,其父类都是Object类,如果一个类没有特别指定父类,那么它默认继承自Object类。
常用方法
-
protected Object clone()
- 创建并返回此对象的副本(克隆)
-
public boolean equals(Object obj)
- 比较两个对象的地址值是否一致,一致返回true,否则返回false
- 可以理解为*"你 == 我 "* ,即是否为同一个人(对象)
-
protected void finalize()
- 该方法会在GC机制准备回收对象内存空间时被调用
- 一般用于释放非java资源(如打开的文件资源,数据库连接等…)
-
public int hashCode()
- 返回该对象的hash值。默认情况下,该方法会根据对象的地址来计算hash值
- 不同的对象的hash值不同,类似于每个人的身份证
-
public final class getClass()
- 返回当前对象运行时的类
- 该类还有一个方法 public String getName() ,可以通过getClass()这个类的getName()方法,来获取对象的真实类的全名称
-
public String toString()
- 返回当前对象的字符串表示
- 底层代码如下:
返回的是类的全路径名+hash值; 但在实际开发中,我们一般会重写掉toString()方法,不会使用Object的toString(),因为其没有什么意义…
方法toString()重写如下:
public class Person{
//Person类默认继承(extends)Object类
//成员变量:定义在类中且方法外的变量
private String name;
private int age;
@Override
public String toString() {
//重写的toString()方法
return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
- public boolean equals(Object obj)
-
比较两个对象是否相等,默认是地址与地址之间的比较; 如果没有覆盖重写equals方法,那么Object类中只要不是同一个对象,比较结果必然为false。
-
若希望进行对象内容之间的一个比较,则必须重写该方法,以实现对象之间进行内容的比较
-
注意:若对象为null,调用其equals()方法时,会抛NullPointException异常,下面的Objects中的equals方法解决了该问题.
-
方法重写代码如下:
import java.util.Objects;
public class Person {
private String name;
private int age;
//有参构造函数
public Person(String name,int age){
this.name = name;
this.age = age;
}
@Override // Person类重写了Object类中的equals()方法
public boolean equals(Object obj) {
// 如果对象地址一样,则认为相同
if (this == obj)
return true;
// 如果参数obj为空,或者类型(类)信息不一样,则认为不同对象,直接返回false
if (obj == null || getClass() != obj.getClass())
return false;
Person person = (Person) obj; // 转换为当前类型
// 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法判断结果
return age == person.age && Objects.equals(name, person.name);
}
}
Objects类
在上面重写equals()方法时,相信大家已经看到了一个Objects类的引用,那么这个类是什么呢?
来源:java.util.Objects
在JDK7后添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode、返回对象的字符串表示形式(toString)、比较两个对象(equals)等。
上面已经说了在比较两个对象的时候,Object的equals方法容易抛出空指针异常(当对象为null时),而Objects类中的equals方法就优化了这个问题。方法如下:
public static boolean equals(Object obj,Object obj)
判断两个对象是否相等(比较内容而非地址)
源码如下:
可以看到它底层的源码也调用了Object.equals()
方法,并且进行了a是否为null的一个判断,如果为null的话,后面的a.equals(b)
必然是不会调用的,所以巧妙地避免了NullPointException异常
常用方法
除了上面列出的日常开发中使用的最多的equals()方法外,还存在一些其他方法
- public static int hash(Object values)
- 为输入值生成一个hash值并返回
- public static boolean isNull(Object obj)
- 对输入的obj判断其是否为null,为null返回true,否则返回false
- public static boolean nonNull(Object obj)
- 对输入的obj判断其是否不为null,不为null返回true,为空返回false
String类
来源: java.lang.String
Java程序中所有双引号(" ")内的字符都属于字符串(String),字符串创建后其值存在于JVM的方法区内存当中,并且其定义的值在创建后就不能被改变
String s1 = "abc";
s1 += "d";
System.out.println(s1); // "abcd"
// 方法区内存中有"abc","abcd"两个字符串对象,s1从指向"abc",改变指向,指向了"abcd"
正因为String类型的数据一旦定义就不能修改,所以如果你创建一个前面已经被创建过的字符串,后创建的字符串会先在方法区内存的字符串常量池(实例池)中寻找该字符串,若不存在则自己创建一个,如果存在就指向那个已存在的值,所以他们的值是可以被共享的。
String s1 = "abc"; //"abc"在方法区内存的常量池中被定义, s1指向该字符串"abc"
String s2 = "abc"; //s2先在常量池中寻找字符"abc",存在则直接指向它,不存在则自己定义一个,并且指向它
// 总结:内存中只有一个"abc"对象被创建,同时被s1和s2共享。
字符串 “abc” 等效于 char[] strs = { ‘a’ , ‘b’ , ‘c’ } ;
String str = “” 等效于 String str = new String( );
//例如:
String str = "abc";
//相当于:
char data[] = {
'a', 'b', 'c'};
String str = new String(data); // String底层是靠字符数组实现的
常用的构造方法
方法名 | 说明 |
---|---|
new String( ) | 创建一个空白字符串对象,不含任何内容 |
new String(char[] chs) | 根据字符数组的内容,来创建字符串对象 |
new String(byte[] bys) | 根据字节数组的内容,来创建字符串对象 |
String s = “abc” | 直接赋值的方式创建字符串对象,内容就是abc |
常用方法
- public int length ()
- 返回此字符串的长度。
- public String concat (String str)
- 将指定的字符串连接到该字符串的末尾。
- public char charAt (int index)
- 返回指定索引处的 char值。
- public int indexOf (String str) :
- 返回指定子字符串第一次出现在该字符串内的索引,没有则返回-1。
- public String substring (int beginIndex)
- 返回一个子字符串,从beginIndex开始截取字符串到字符串结尾。
- public String substring (int beginIndex, int endIndex)
- 返回一个子字符串,从beginIndex到endIndex截取字符串,含beginIndex,不含endIndex。
StringBuffer类
来源: java.lang.Object
StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的内容是可变的,因为其底层数组没有采用final
关键字修饰,所以该数组是可变的,而String类底层的数组被final
修饰,所以一旦创建就不可更改,这就是二者之间的最大区别~
构造方法介绍
构造方法名 | 说明 |
---|---|
new StringBuffer() | 构造一个没有字符的字符串缓冲区,初始容量为16个字符。 |
new StringBuffer(CharSequence seq) | 构造一个含有指定seq内容的字符串缓冲区,初始容量为16+seq的长度 |
new StringBuffer(int capacity) | 构造一个没有字符的字符串的缓冲区并指定其初始容量 |
new StringBuffer(String str) | 构造一个初始化为指定字符串内容str的字符串缓冲区 |
常用方法
注意:以下StringBuffer类中所有涉及到下标的方法,其下标都从0开始,并且区间范围都属于半闭半开[begin,end )
-
append()
- 可以添加一个任意基本数据类型或char[]数组,并且可以指定截取char[]数组的指定部分
-
insert()
- 可以在指定位置插入数据(数据:基本数据/数组)
-
charAt(int index)
- 返回指定索引处的字符,不会改变原数组
-
codePointAt(int index)
- 返回指定下标处字符对应的Unicode码
-
delete(int begin, int end)
- 删除字符串中指定[begin,end)处的字符,会改变原字符串缓冲区
-
deleteCharAt(int index)
- 删除index索引处的字符,并改变原字符串缓冲区
-
indexOf(String str)
- 返回指定子串str在母串中第一次出现的索引,没有出现则返回-1
-
indexOf(String str, int index)
- 返回指定子串str在母串中第一次出现的索引,开始检索处由index下标确定
-
replace( int begin, int end, String str)
- 用指定的str替换[begin,end)之间的字符串,会改变原字符串缓冲区,替换字符不包含end处元素
-
reverse()
- 反转字符串缓冲区的内容,会改变原串
-
setCharAt(int index, char ch)
-
将指定索引处的字符用ch代替,若index下标超过字符串缓冲区总长度,则会抛出字符串索引越界异常"StringIndexOutOfBoundsException"
代码如下:
package com.obtk.day18; public class Demo01 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("abced"); //当前总长度为5,不存在下标为7的元素 sb.setCharAt(7,'p'); System.out.println(sb); } }
执行结果如下:
注:总长度length为5,下标index为7,所以会抛异常错误!!
StringBuffer和String如何相互转换?
可以借助StringBuffer类的toString( )方法将StringBuffer转换为String类型
可通过StringBuffer的构造方法将String类型转换为StringBuffer类型
例如 :new StringBuffer(String str);
具体实现代码如下:
public class StringBufferDemo02 { public static void main(String[] args) { //StringBuffer 转换为 String StringBuffer sb = new StringBuffer(); sb.append("hello"); //添加"hello"到字符串缓冲区 String s = sb; //这个是错误的做法 //public String toString() //通过 toString()就可以实现把 StringBuffer转换为String String s = sb.toString(); System.out.println(s); // String 转换为 StringBuffer String s = "hello"; //StringBuilder sb = s; //这个是错误的做法 //通过构造方法就可以实现把 String 转换为 StringBuffer StringBuffer sb = new StringBuffer(s); System.out.println(sb); // 输出hello } }
String和StringBuffer比较(区别)
- String表示是字符串常量,一旦创建后,内容和长度都是无法改变的。而StringBuffer表示字符容器,其内容和长度都可以随时修改
- 只是表示字符类型,使用String类,如果要做增删操作或对要求字符串变化较多,建议使用StringBuffer
- String类覆盖了Object类的equals方法,而StringBuffer类没有覆盖Object类的equals方法
- String类对象可以用操作符"+“进行连接,而StringBuffer类对象之间不能用”+"进行连接
-
日期时间(Date)类
来源: java.util.Date
在日常生活中,有一个东西一直伴随着我们,那就是时间。java作为一门热门的高级语言,自然也为我们提供了一些对时间进行操作的类,例如Date,DateFormat,SimpleDateFormat,现在,我们就从以上三个类开始,对日期时间类进行一些简单的介绍
通过查阅API文档,我们发现Date拥有多个构造函数,只是部分已经过时,但是其中有未过时的构造函数可以把毫秒值转成日期对象。常用的两种构造方法如下:
-
new Date()
: 分配一个Date对象并初始化此对象,以便它表示分配的时间(精确到最近毫秒) -
new Date(long date)
:分配Date对象并初始化此对象,以表示从标准基准时间(称为“历元(epoch)",即1970年1月1日00:00:00 GMT)以来的指定毫秒数。
public class Demo03 {
public static void main(String[] args) {
//获取1970-1-1 0:0:0 到其1000毫秒之后的时间
Date date = new Date(1000);
//(注:由于我们处于东八区,所以我们的基准时间为1970年1月1日8时0分0秒。)
//输出1970-1-1 8:0:01
System.out.println(date);
}
}
Date类中的多数方法已经过时,留存下来算常用的还有如下几种:
- public boolean after(Date when)
- 测试此日期是否在指定日期之后,若是则返回true,否则返回false
- public boolean before(Date when)
- 测试此日期是否在指定日期之前,若是则返回true,否则返回false
- public long getTime()
- 返回自1970年1月1日以来的总毫秒数(注 : 1秒 = 1000毫秒)
java.text.DateFormat 是日期/时间格式化子类的抽象类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换,将其转换成我们所了解的形式。
构造方法
由于DateFormat为抽象类,不能直接使用,所以需要常用的子类public SimpleDateFormat(String pattern)
这个类来进行实例化,
注: 参数pattern是一个字符串,代表日期时间的自定义格式
一般格式如下:
//实例化日期/时间格式化对象SimpleDateFormat,并自定义其转换格式
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
常用格式规则如下
标识字母(区分大小写) | 含义 |
---|---|
y | 年 |
M | 月 |
d | 日 |
H | 小时 |
m | 分钟 |
s | 秒 |
备注:更详细的格式规则,可以参考SimpleDateFormat类的API文档
DateFormat类的常用方法有
- public String format(Date date) :将Date对象按照一定格式转换成字符串
- public Date parse(String source):将字符串解析成Date对象
使用format方法的代码如下:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/*把Date对象转换成String*/
public class Demo04DateFormatMethod {
public static void main(String[] args) {
Date date = new Date(); //获取日期
// 创建日期格式化对象,在获取格式化对象时可以指定风格
DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
//将date对象按照"yyyy年MM月dd日"的格式转换为字符串
String str = df.format(date);
System.out.println(str); // 2008年1月23日
}
}
使用parse方法的代码如下:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/* 把String转换成Date对象*/
public class Demo05DateFormatMethod {
public static void main(String[] args) throws ParseException {
/*注意:字符串年月日的格式必须和df后面指定的格式一致,否则无法正确转换*/
//设定df时间对象的日期格式
DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
String str = "2018年12月11日";
//将字符串str转换为Date类型的日期格式
Date date = df.parse(str);
System.out.println(date); // Tue Dec 11 00:00:00 CST 2018
}
}
Calendar类
来源:java.util.Calendar
java.util.Calendar是日历类,在Date类后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。日历类就是方便获取各个时间属性的一个工具类。
因为Calendar为抽象类,所以由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态方法public static Calendar getInstance()
创建,返回子类对象,如下
import java.util.Calendar;
public class Demo06CalendarInit {
public static void main(String[] args) {
//调用Calendar的静态方法创建对象,使用默认时区和语言获得一个日历
Calendar cal = Calendar.getInstance();
}
}
常用方法
- public int get(int field)
- 返回给定日历字段的值
- public void set(int field, int value)
- 将给定的日历字段设置为给定值value
- public abstract void add(int field, int amount)
- 为给定的日历字段field添加或减去指定的时间量amount
- public Date getTime()
- 返回一个Date类型的当前时间,类似于使用Date对象new出来的当前时间对象
Calendar提供了很多成员变量,代表给定的日历字段
字段值 | 含义 |
---|---|
YEAR | 年 |
MONTH | 月(从0开始) |
DAY_OF_MONTH | 一个月中的第几天 |
HOUR | 小时(12小时制) |
HOUR_OF_DAY | 小时(24小时制) |
MINUTE | 分 |
SECOND | 秒 |
DAY_OF_WEEK | 一周中的某一天 |
注:西方星期的开始为周日,中国为周一。在Calendar类中,月份的表示是以0-11代表1-12月。日期是有大小关系的,时间靠后,时间越大。
package com.obtk.day20;
//导入外部工具包
import java.time.Year;
import java.util.Calendar;
public class Demo02 {
public static void main(String[] args) {
//实例化日历对象
Calendar c1 = Calendar.getInstance();
System.out.println(c1.getTime());
System.out.println(c1.get(Calendar.DAY_OF_MONTH)); //获取当月天数
System.out.println(c1.get(Calendar.YEAR));//获取年份
c1.set(Calendar.YEAR,1995); //设置年份为1995
System.out.println(c1.get(Calendar.YEAR));
c1.add(Calendar.YEAR,-3); //当前年份减去3,得到新年份1992
System.out.println(c1.get(Calendar.YEAR));
System.out.println(c1.get(Calendar.DAY_OF_WEEK)); // 返回 周几
}
}
以上代码输出如下:
System类
java.lang.System类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作,在System类的API文档中,常用的方法有:
-
public static long currentTimeMillis()
- 获取当前系统时间与1970年01月01日00:00点之间的毫秒差值,一般用于测试程序的效率
-
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
- 将数组中指定位置间的元素截取到另外一个数组的指定位置
- 传入5个参数:
src: 表示源数组
dest :目标数组
srcPos : 源数组中拷贝元素的起始位置
descPos :拷贝到目标数组的起始位置
length :拷贝元素的个数 - 注意:在进行数组复制时,一定要有足够的空间来存放拷贝的元素,否则会发生角标越界异常
-
static Properties getProperties()
- 获取当前的系统全部属性
-
static String getProperties()
- 获取当前的系统属性
-
static long gc()
- 运行垃圾回收器,并对垃圾进行回收
-
static void exit(int status)
- 该方法用于终止当前正在运行的java虚拟机,其中参数status表示状态码,若状态码非0,则表示异常终止
代码演示如下:
package com.obtk.day20; import java.util.Arrays; //数组拷贝System.arraycopy()方法演示 public class Demo03 { public static void main(String[] args) { int[] arr1 = new int[]{ 1,2,3,4,5}; int[] arr2 = new int[]{ 6,7,8,9,10}; //代表从arr1的索引0处复制元素到arr2中索引为2处,并且复制三个元素 System.arraycopy(arr1,0,arr2,2,3); System.out.println(Arrays.toString(arr2));//运行结果: [6,7,1,2,3] } }
Runtime类
用于表示虚拟机运行时的状态,里面封装JVM虚拟机运行。每次使用java命令启动虚拟机都对应一个Runtime实例。并且只有一个实例;该类采用单例模式进行设计。
单例模式:保证整个系统中一个类只有一个对象的实例,实现这种功能的方式就叫单例模式
了解:单例模式的好处:
1. 节省公共资源 2. 方便控制
测试自己的电脑是多少核的代码:
public class Demo03Runtime {
public static void main(String[] args) {
//获得一个Runtime的实例
Runtime rt = Runtime.getRuntime();
System.out.println("处理器的个数:"+rt.availableProcessors()+"个");
//默认单位字节
System.out.println("空闲内存数"+rt.freeMemory()/1024/1024+"M");
System.out.println("最大可用内存数"+rt.maxMemory()/1024/1024+"M");
}
}
通过代码打开系统中的应用程序:采用Runtime类的exec( )方法; 代码如下:
public class Demo04Runtime2 {
public static void main(String[] args) throws IOException, InterruptedException {
//创建Runtime实例对象
Runtime runtime = Runtime.getRuntime();
//打开记事本 等于产生一个新的进程
Process process = runtime.exec("notepad.exe");
//程序休眠3秒 3秒后继续执行下面的程序
Thread.sleep(3000);
//杀掉(关闭)进程
process.destroy();
}
}
常用查找算法:
- BinarySearch():二分查找法
代码演示如下:
package com.obtk.day20;
import java.util.Arrays;
/*1.二分查找法*/
public class Demo04 {
public static void main(String[] args) {
int[] arr = new int[]{
98,78,45,12,45,11,55};
//二分查找法的前提条件就是元素处于升序状态
Arrays.sort(arr);
System.out.println(myBinarySearch(arr,11));
}
public static int myBinarySearch(int[] arr,int num){
int left = 0; //获取起始下标
int right = arr.length-1; //获取最后一个元素下标
while(left <= right){
//left小于right,代表所有区间始终大于等于1
int mid = (left+right)/2; //获取区间中间值
//判断中间值是否是我们要找的nunm
if (arr[mid] == num){
return mid; //若是则直接返回其下标
}else if(arr[mid] > num){
//num元素小于中间值,表示mid右边所有值都比num大,所以右边的值都不需要比较,缩短右边区间到mid-1处
right = mid-1;
}else if(arr[mid] < num){
//num大于中间值,即大于所有中间值mid左边的值,那么左边的值也无需比较,直接缩短左边区间到mid+1处
left = mid + 1;
}
}
return -1;
}
}
- 暴力搜索法
代码演示如下:
package com.obtk.day20;
import java.util.Arrays;
/*2.暴力搜索法:找出有序数列中指定元素的索引*/
public class Demo05 {
public static void main(String[] args) {
int[] arr = new int[]{
98,78,45,12,45,11,55};
Arrays.sort(arr); //搜索前对元素进行排序
System.out.println(Search(arr,11));
}
public static int Search(int arr[],int num){
for (int i = 0; i < arr.length; i++) {
if (arr[i] == num){
//通过循环一个一个比较
return i;
}
}
//找不到元素就返回-1
return -1;
}
}
作者:胡亦
时间:2021年11月29日22:06:43
创作不易,希望大家多多点赞支持以下~~