常用类
Object类
所有类都直接或间接的继承java,lang.Object类
该类中主要有以下方法:
- toString()
- getClass()
- equals()
- clone()
- finalize()
其中getClass(),notify(),notifyAll(),wait()等方法都是final类型不能被重写
clone()方法
clone()就是复制对象,在java中可以通过clone()来复制一个对象;
在Object类中clone()方法只是简单执行域对域的复制(浅复制),需要重写clone()方法可以实现深复制,把域里面的子域也进行clone()
如图,Object类中的clone()并没有对hireDay进行clone,所有在Employee类中要重写clone()方法
class Employee implements Cloneable { public Object clone() throws CloneNotSupportedException { Employee cloned = (Employee) super.clone(); cloned.hireDay = (Date) hireDay.clone(); return cloned; } }
java中的clone()是被声明为protected的,只有同包下,及其子类才能克隆该对象
调用clone()方法的对象所属的类必须实现Cloneable接口
finalize()方法
该方法用于释放资源;其工作原理是:一旦垃圾回收器准备好释放对象占用的存储空间将首先调用其finalize()方法。在下一次垃圾回收之前,才会真正的回收对象占用的内存。
equals()方法
在Object类中,功能与==一样,都是判断对象的内存空间是不是同一个。
String类里重写了equals()方法,来比较字符串的内容是否相等。
hashCode()方法
返回对象的哈希码值,该方法用于哈希查找,可以减少使用equals()的次数,一般重写了equals方法都要重写hashCode方法;如果obj1.equals(obj2),则一定有obj1.hashCode()==obj2.hashCode();反之不一定。
wait(),notify()和notifyAll()
wait()是让当前线程释放它所持有的锁并进入等待状态,直到其他对象调用notify(),notifyAll()方法当前线程才会被唤醒,notify()/notifyAll()是唤醒当前对象上的某一个/所有线程
包装类
每个基本数据类型都对应一个包装类
基本数据类型 | 对应包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
装箱和拆箱
基本类型转换为包装类就是装箱
包装类转换为基本类型就是拆箱
public static void main(String[] args) { //Integer,int int a=10; //手动装箱,1.8后,会1进行自动装箱和拆箱 Integer b=new Integer(a); //手动拆箱 int c=b.intValue(); //静态方法,将字符串转换为整数 Integer.parseInt("123"); //静态方法,将整数转换为字符串 Integer.toString(1); }
Integer类对于-128-127的值会采用缓存机制,使用Integer a=10;创建-128-127以内的值(除开new)时会采用缓存机制,即再次创建时会从缓存中取实例,两者地址相同
Random类
Java中存在两种Random函数
java.lang.Math.Random()
返回带正号的double值,该值在[0.0,0.1)左闭右开区间,返回一个为随机数
java.util.Random
Random():创建一个新的随机数生成器
Random(long seed):使用种子seed创建一个新的随机数生成器
种子数表示随机算法的起源数字
public class JavaTest { public static void main(String[] args) { //不指定seed,seed为当前系统的毫秒数 Random random=new Random(); //产生0-99的整数 System.out.println(random.nextInt(100)); //使用相同种子生成的随机数序列相同 Random random1=new Random(10); for(int i=0;i<10;i++){ System.out.println(random1.nextInt(100)+" "); } } }
Date类
java.util包来提供Date类封装当前日期和时间
public static void main(String[] args) { //获取当前日期 Date date=new Date(); //getTime()获取日期(1970年1月1日到现在的毫秒数值) System.out.println(date.getTime()); //before(),after()比较当前对象是否在日期前或者后 System.out.println(date.before(new Date(2021,4,30))); }
SimpleDateFormat类
格式化日期
public static void main(String[] args) { Date date = new Date(); //自定义日期格式,hh表示12小时制,HH表示24小时制度 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); System.out.println(simpleDateFormat.format(date)); }
Calendar类
Calendar类是一个抽象类,只需要使用getInstance()就可创建对象
public class JavaTest { public static void main(String[] args) { //创建一个指定的日期 Calendar calendar=Calendar.getInstance(); calendar.set(2021,12,21); //Calendar.YEAR获取年份,Calendar.Month获取月份,Calendar.DATE获取天数,Calendar.HOUR获取小时 //Calendar.MINUTE获取分钟,Calendar.SECOND获取秒数 System.out.println(calendar.get(Calendar.YEAR)); System.out.println(calendar.get(Calendar.MONTH)); System.out.println(calendar.get(Calendar.DATE)); System.out.println(calendar.get(Calendar.HOUR)); System.out.println(calendar.get(Calendar.MINUTE)); } }
Calendar类的月份是从0开始的,日期和年份是从1开始的
String类
字符串是常量,在创建后不能更改;String类的底层是由一个final修饰的字符数组来实现的,存储String数据也不一定是从数组的第0个下标元素开始,而是从offset属性指定的元素下标开始
public class JavaTest { public static void main(String[] args) { //直接赋值创建与实例化创建 String s1="dwx"; String s2=new String("dwx"); String s3=s2; String s4="dwx"; System.out.println(s1==s2);//false System.out.println(s2==s3);//true System.out.println(s1==s4);//true } }
1.在字符串中,如果采用直接赋值的方式创建对象,会开辟一块堆内存保存匿名对象并将匿名对象存入字符串常量池,当再有通过直接赋值该字符串对象时,直接使用池里的对象,而不会重新创建。每一个字符串常量都是String类的匿名对象
2.使用实例化方式(new)创建字符串会开辟两块堆内存,因为每一个字符串常量都是String类的匿名对象,所以在new一个字符串时,会先在堆内存中开辟一块空间用来存储匿名对象,然后再开辟一块空间存储new出来的字符串,此时字符串常量的匿名对象的空间没有被使用,成为垃圾空间,等待GC回收。且由于是new一个对象,所以内容不会被保存再字符串常量池中。
因此一般不采用实例化的方式创建字符串
使用equals()方法来比较字符串变量和常量时,常量在前变量在后即"常量".equals("变量")
常用方法
字符串常量池
常量池表
class文件中存储所有常量的table。
运行时常量池
是jvm内存中方法区的一部分,是运行时的内容;随着JVM运行时,从常量池转化过来的
字符串常量池
也在方法区,是JVM实例全局共享的,全局只有一个
享元模式
共享元素模型:一个系统中如果由多处用到了相同的元素,就应该只存储一个该元素,让所有其他地方都引用该元素
String str=new String("abc")时会创建几个对象
1个或者2个;JVM遇到上述代码时,会先检查常量池中是否存在“abc“,如果不存在,则会现在常量池中创建一个该字符串,然后执行new操作,会在堆上创建一个存储“abc”的对象,此过程创建了2个对象;如果检查发现常量池已经存在了该字符串,就只会在堆内创建一个新的String对象,该过程只创建了一个对象
StringBuilder和StringBuffer
StringBuilder是一个可变的字符序列,继承与AbstractStringBuilder,实现了CharSequence接口,是非线程安全的。
StringBuffer也是继承与AbstractStringBuilder的子类,是线程安全的,
常用方法
public class JavaTest { public static void main(String[] args) { //inset()插入,可以插入字符串,字符数组,基本数据类型等 StringBuilder stringBuilder=new StringBuilder(); stringBuilder.insert(0,"ddddddd"); System.out.println(stringBuilder); //append()追加 stringBuilder.append("wwwww"); System.out.println(stringBuilder); //appendCodePoint(unicode编码) stringBuilder.appendCodePoint(0x5b57); //replace()替代,不包括end的索引 stringBuilder.replace(0,4,"xxxxxxxxxxxx"); System.out.println(stringBuilder); //setCharAt(),将指定索引位置字符替换为指定字符 stringBuilder.setCharAt(0,'a'); System.out.println(stringBuilder); //reverse(),反转 stringBuilder.reverse(); System.out.println(stringBuilder); //deleteCharAt()删除指定索引位置的字符 stringBuilder.deleteCharAt(0); System.out.println(stringBuilder); //substring()获取子串,返回String String sub=stringBuilder.substring(1,4); System.out.println(sub); //subSequence()返回CharSequence String subs=(String) stringBuilder.subSequence(1,4); System.out.println(subs); //delete()删除指定索引间的字符 stringBuilder.delete(0,4); System.out.println(stringBuilder); //indexOf()查找字符串第一次出现的索引位置 System.out.println(stringBuilder.indexOf("xa")); System.out.println(stringBuilder.indexOf("x",4)); //lastIndexOf()从后往前找字符串第一次出现的位置 System.out.println(stringBuilder.lastIndexOf("xx")); System.out.println(stringBuilder.lastIndexOf("x",4)); //capacity()返回字符串缓冲区的容量 System.out.println(stringBuilder.capacity()); } }
总结
- 如果操作少量数据使用String
- 单线程下操作大量数据用StringBuilder
- 多线程下操作大量数据用StringBuffer
File类
java,io.File类:文件和目录路径名的抽象表示形式
File类的静态变量separator存储了当前系统的路径分隔符
常见的一些构造器和方法
public class JavaTest { public static void main(String[] args) throws IOException { File file1=new File("F:\\Java笔记\\testj.java"); File file2=new File("F:\\Java笔记"); File file3=new File(file2,"testj.java"); //创建文件 file3.createNewFile(); //是否是一个文件 System.out.println(file2.isFile()); //是否是一个目录 System.out.println(file2.isDirectory()); } }