String类
-
String类型的字符串存储原理
/* 关于java JDK中内置的一个类:java.util.String 1、String表示字符串类型,属于引用数据类型,不属于基本数据类型。 2、在java中随便使用双引号括起来的都是String对象,例如:"abc","def","hello" 这是3个String对象 3、java中规定:双引号括起来的字符串,是不可改变的。也就是说:"abc"从创建到释放,不可变,不能变成"abc",也不能变成"ab" 4、在JDK当中双引号括起来的字符串,例如:"abc","def"都是直接存储在“方法区”中的“字符串常量池”当中的 为什么SUN公司把字符串存储在一个“字符串常量池”中呢? 因为字符串在实际开发中使用太频繁,为了执行效率,所以把字符串放到了方法区中的字符串常量池中 */ public class StringText01 { public static void main(String[] args) { //这两行代码表示底层创建了3个字符串对象,都在字符串常量池中。 String s1 = "abcdef"; String s2 = "abcdef"+"xy"; //分析:这是使用new的方式创建的字符串对象,这个代码中的"xy"是从哪里来的? String s3 = new String("xy"); //凡是双引号括起来的都在字符串常量池中有一份。new对象的时候一定在堆内存中开辟空间 //i变量中保存的是100这个值 int i = 100; //s变量中保存的是字符串对象的内存地址,s引用中保存的不是"abc",而是0x1111——"abc"字符串对象在“字符串常量池”中的内存地址 String s = "abc"; } }
public class User { private int id; private String name; public User(){ } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class UserText { public static void main(String[] args) { User user = new User(110,"张三"); } }
-
字符串的比较为什么要使用equals方法
public class StringText02 { public static void main(String[] args) { String s1 = "hello"; String s2 = "hello"; //分析输出结果是true还是false == 比较的是变量中保存的内存地址。 System.out.println(s1 == s2); //true //s1的"hello"是存储在方法区的常量池中,所以s2的"hello"不会新建。(因为这个对象已经存在了) //s1和s2都存储的是字符串常量池中"hello"的内存地址。 String x = new String("xyz"); String y = new String("xyz"); //分析输出结果是true还是false System.out.println(x == y);//false //x与y创建字符串对象是通过new出来的,在堆中开辟了两块内存空间,虽然堆中的String保存了字符串常量池中的"xyz"的内存地址 //但x与y这两个对象的内存地址不一样,是存储在堆中的两个String类型对象,而这两个对象的内存地址不同 //通过本案例学习,我们知道了:字符串对象之间的比较不能使用“==”,“==”不保险,应该使用String类的equals方法 System.out.println(x.equals(y));//true //String类已经重写了equals方法,以上的equals方法调用的是String重写之后的equals方法 String k = new String("textString"); //因为"textString"是一个String字符串对象。只要是对象,都可以调用方法 System.out.println("textString".equals(k));//true 建议使用这种方式,因为这个可以避免空指针异常 System.out.println(k.equals("textString"));//true 如果k为空,就会出现空指针异常。不建议使用这种方式 } }
-
String类的面试题一个
//分析以下程序,一共创建了几个对象 3个 public class StringText03 { public static void main(String[] args) { /* 一共三个对象: 方法区字符串常量池中一个:"hello" 堆内存中:两个String类型对象 一共三个 */ String s1 = new String("hello"); String s2 = new String("hello"); } }
-
String类中的构造方法
/** * 关于String类中的构造方法 * 第一个:String s = new String(""); * 第二个:String s = ""; 最常用 * 第三个:String s = new String(byte数组); * 第四个:String s = new String(byte数组,起始下标,长度) * 第五个:String s = new String(char数组); * 第六个:String s = new String(char数组,起始下标,长度); */ public class StringText04 { public static void main(String[] args) { //创建字符串对象最常用的一种方法 String s1 = "hello world"; //s1这个变量中保存的是一个内存地址,按说以下应该是输出一个内存地址,但却输出了一个字符串。说明String类已经重写了toString()方法 System.out.println(s1); //hello world System.out.println(s1.toString()); //hello world //这里只掌握常用的构造方法 byte[] bytes = {97,98,99}; //97是a ,98 是b,99是c String s2 = new String(bytes); System.out.println(s2.toString()); //abc System.out.println(s2); //abc //之前说:说出一个引用的时候,会自动调用toString()方法,默认Object的话,会自动输出对象的内存地址 //通过输出结果我们得出一个结论:String类已经重写了toString方法。输出字符串对象的话,输出的是字符串本身,而不是对象的内存地址。 /** * 将byte数组中的一部分转换成字符串 * String(字节数组,从哪里开始:数组元素的下标,长度) */ String s3 =new String(bytes,0,1); System.out.println(s3); //将char数组全部转换成字符串 char[] chars = {'我','爱','R','M','币'}; String s4 = new String(chars); System.out.println(s4); //将char数组的一部分转换成字符串 String s5 = new String(chars,2,3); System.out.println(s5); } }
-
String类中需要掌握的一些方法
//String类当中的常用方法 public class StringText05 { public static void main(String[] args) { //1(掌握).char charAt(int index) 输出String对象下标为index的字符 char c = "人民币".charAt(1); //“中国人”是一个字符串String对象,只要是对象就能“.” System.out.println(c); //民 //2(了解).int compareTo(String anotherString) int result = "abc".compareTo("abc"); System.out.println(result); //0 前后一致 10 - 10 = 0 int result2 = "abcd".compareTo("abce"); System.out.println(result2);//-1 前小后大 8 - 9 =-1 int result3 = "abcecd".compareTo("abcdce"); System.out.println(result3);//1 前大后小 9 - 8 = 1 //拿着字符串第一个字母和后面字符串比较。能分出大小就不再比较了。哪个字母的顺序靠后,哪个字母就大 //如果一个字符串有多个字符,返回值:靠后的字母的顺序-靠前的字母的顺序 System.out.println("xyz".compareTo("yxz")); //-1 System.out.println("a".compareTo("z"));//-25 System.out.println("z".compareTo("a"));//25 System.out.println("ac".compareTo("zd"));//-25 //3(掌握).boolean contains(CharSequence s) //判断前面的字符串中是否包含后面的字符串,包含:返回true 不包含:返回false System.out.println("HelloWorld.java".contains(".java"));//true System.out.println("http://www.baidu.com".contains("https:"));//false //4(掌握 ).boolean endsWith(String suffix) //判断当前字符串是否以某个字符串结尾 System.out.println("test.txt".endsWith(".txt"));//true System.out.println("test.txt".endsWith(".java"));//false System.out.println("dafkhsdlgkjdfglksdfhaiotghjdfgdd".endsWith("gdd"));//true //5(掌握).boolean equals(Object anObject) //比较两个字符串必须使用equals方法,不能使用“==”,那equals方法有没有调用compareTo方法呢?//新版本的JDK中没有调用 //compareTo方法可以看出是否相等,并且同时还可以看出谁大谁小。 System.out.println("abc".equals("abc")); //6(掌握).boolean equalsIgnoreCase(String anotherString) //判断两个字符串是否相等,并且同时忽略大小写 System.out.println("ABc".equalsIgnoreCase("abC"));//true //7(掌握).byte[] getBytes() //将字符串对象转换成字节数组 byte[] bytes = "abcdef".getBytes(); for (int i = 0; i <bytes.length ; i++) { System.out.println(bytes[i]);// 97 98 99 100 101 102 } //8(掌握).int indexOf(String str) //判断某个子字符串在当前字符串中第一次出现的索引(下标) System.out.println("oraclejavac++.netc#phppythonjavaoraclec++".indexOf("java"));//6 //9(掌握).boolean isEmpty() //判断某个字符串是否为空字符串。当且仅当length为0时为true //String s = ""; String s = "a"; System.out.println(s.isEmpty()); //false //10(掌握). int length() //面试题:判断数组长度和判断字符串长度不一样 //判断数组长度和判断字符串长度不一样,判断数组长度的是length属性,判断字符串长度的是length()方法。 System.out.println("abc".length());//3 System.out.println("".length());//0 长度为0 即:字符串为:空串 //11(掌握). int lastIndexOf(String str) //判断某个子字符串在当前字符串中最后一次出现的索引(下标) System.out.println("oraclejavac++.netc#phppythonjavaoraclec++".lastIndexOf("java"));//28 //12(掌握). String replace(CharSequence target , CharSequence replacement) 替换 //String的父接口是:CharSequence String newString ="http://www.baidu.com".replace("http","https"); System.out.println(newString); //https://www.baidu.com //把以下字符串中的“=”替换成“:” String newString2 ="name=zhangsan&password=123&age=20".replace("=",":"); System.out.println(newString2);//name:zhangsan&password:123&age:20 //13(掌握). String[] split(String regex) 拆分字符串,用一个数组接收 String[] ymd ="1980-08-10".split("-"); for (int i = 0; i <ymd.length ; i++) { System.out.println(ymd[i]); } String param = "name:zhangsan&password:123&age:20"; String[] params =param.split("&"); for (int i = 0; i <params.length ; i++) { System.out.println(params[i]); //可以继续向下拆分,可以通过“:”拆分 } //14(掌握). boolean startWith(String prefix) //判断某个字符串是否以某个子字符串开始。 System.out.println("http://www.baidu.com".startsWith("http"));//true System.out.println("http://www.baidu.com".startsWith("https"));//false //15(掌握). String substring(int beginIndex) 参数是起始下标 截取字符串 System.out.println("http://www.baidu.com".substring(7)); //www.baidu.com //16(掌握). String substring(int beginIndex,int endIndex) 截取部分字符串 //beginIndex 起始位置(包括) endIndex 结束位置(不包括) System.out.println("http://www.baidu.com".substring(7,10)); //www //17(掌握). char[] toCharArray() //将字符串转换成char数组 char[] chars = "我是中国人".toCharArray(); for (int i = 0; i <chars.length ; i++) { System.out.println(chars[i]); } //18(掌握). String toLowerCase(); 全部转换成小写 System.out.println("ABCDefkXyz".toLowerCase()); //abcdefkxyz //19(掌握). String toUpperCase(); 全部转换成大写 System.out.println("ABCDefkXyz".toUpperCase()); //ABCDEFKXYZ //20(掌握). String trim(); 去除字符串前后空白 但字符串中间的空白不能去 System.out.println(" hello world ".trim());//hello world //21(掌握). String中只有一个方法是静态的,不需要new对象 这个方法叫:valueOf 作用:将“非字符串”转换为“字符串” String s1 = String.valueOf(true); String s2 = String.valueOf(100); String s3 = String.valueOf(3.14); System.out.println(s1+s2+s3);//true1003.14 //这个静态的valueOf()方法,参数是一个对象的时候,会自动调用该对象的toString方法吗? 会的 String s4 = String.valueOf(new Customer()); //System.out.println(s4); //没有重写toString()方法之前是对象内存地址 Customer@1b6d3586 System.out.println(s4); //重写之后:"我是一个VIP" //我们是不是可以研究一下println()方法的源码了 System.out.println(100); System.out.println(3.14); System.out.println(true); //通过源代码就可以看出:为什么输出一个引用的时候,会调用toString()方法。 //使用System.out.println();输出引用时,调用了valueOf方法,而valueOf方法里又调用了引用的toString方法,所以输出引用时,与输出这个对象的toString方法相同 Object obj = new Object(); System.out.println(obj); //本质上System.out.println();这个方法在输出任何数据的时候都是先转换成字符串再输出。 System.out.println(new Customer());//我是一个VIP } } class Customer{ @Override public String toString() { return "我是一个VIP"; } }
-
如果要进行字符串的频繁拼接
StringBuffer 线程安全
/* 思考:我们在实际开发中,如果需要进行字符串的频繁拼接,会有什么问题? 因为java中的字符串是不可变的,每一次拼接都会产生新字符串。这样会占用大量的方法区内存,造成内存空间的浪费。 String s = "abc"; s += "hello"; 就以上两行代码,就导致在方法区字符串常量池当中创建了3个对象: "abc" "hello" "abchello" */ public class StringBufferText01 { public static void main(String[] args) { String s = ""; //这样做会给java的方法区字符串常量池带来很大的压力 for (int i = 0; i <100 ; i++) { s = s + i; System.out.println(s); } } }
/* 如果以后需要进行大量字符串的拼接操作,建议使用JDK中自带的: java.lang.StringBuffer java.lang.StringBuilder 如何优化StringBuffer的性能? 在创建StringBuffer的时候尽可能给定一个初始化容量。最好减少底层数组的扩容次数,预估计一下,给一个大一些的初始化容量 关键点:给一个合适的初始化容量,可以提高程序的执行效率 */ public class StringBufferText02 { public static void main(String[] args) { //创建一个初始化容量为16的byte[]数组,(字符串缓冲区对象) StringBuffer stringBuffer = new StringBuffer(); //拼接字符串,以后拼接字符串统一调用append()方法。 //append是追加的意思。 stringBuffer.append("a"); stringBuffer.append("b"); stringBuffer.append("d"); stringBuffer.append(3.14); stringBuffer.append(true); //append方法底层在进行追加的时候,如果byte数组满了,会自动扩容 stringBuffer.append(100L); System.out.println(stringBuffer); //执行初始化容量的StringBuffer对象(字符串缓冲区对象) StringBuffer sb = new StringBuffer(25); sb.append("hello"); sb.append("world"); sb.append("hello"); sb.append("kitty"); System.out.println(sb); } }
StringBuilder 非线程安全
/* java.lang.StringBuilder StringBuffer和StringBuilder的区别: StringBuffer中的方法都 有 :synchronized关键字修饰。表示StringBuffer在多线程环境下运行是安全的 StringBuilder中的方法 没有 synchronized修饰,表示StringBuilder在多线程环境下运行是不安全的 StringBuffer是线程安全的 StringBuilder是非线程安全的 */ public class StringBuilderText01 { public static void main(String[] args) { //使用StringBuilder也是可以完成字符串的拼接 StringBuilder sb = new StringBuilder(); sb.append(100); sb.append(true); sb.append("hello"); sb.append("kitty"); System.out.println(sb);//100truehellokitty } }
String为什么不可变,StringBuffer/StringBuilder为什么可变
/* 1、面试题:String为什么是不可变的? 我看过源代码,String类中有一个byte[]数组,这个byte[]数组采用了final修饰,因为数组一旦创建长度不可变。并且被final修饰的引用 一旦指向某个对象之后,不可再指向其他对象,所以String是不可变的! "abc"无法变成"abcd" 2、StringBuilder/StringBuffer为什么是可变的呢? 我看过源代码,StringBuffer/StringBuilder内部实际上是一个byte[]数组,这个byte[]数组没有被final修饰,StringBuffer/StringBuilder 的初始化容量我记得应该是16,当存满之后会进行扩容,底层调用了数组拷贝的方法System.arraycopy() 用来扩容。所以他们适合于使用字符串的频繁拼接操作 */ public class StringBufferText03 { public static void main(String[] args) { //字符串不可变是什么意思? //是说双引号里面的字符串对象一旦创建不可变 String s = "abc"; //“abc”放到了字符串常量池当中,“abc”不可变 //s变量是可以指向其他对象的 //字符串不可变不是说以上变量s不可变。说的是“abc”这个对象不可变 s = "xyz"; //"xyz"放到了字符串常量池当中。“xyz”不可变 } }
包装类
-
java为8种基本数据类型又对应准备了8种包装类型。
package integer; /* 1、java中为8种基本数据类型又对应准备了8种包装类型。8种包装类型属于引用数据类型,父类是Object 2、思考:为什么要再提供8种包装类呢? 因为8种基本数据类型不够用 所以SUN公司又提供对应的8种包装类型。 */ public class IntegerText01 { //入口 public static void main(String[] args) { //有没有这种需求:调用doSome()方法的时候需要传一个参数进去。 //但是数字属于基本数据类型,而doSome()方法参数的类型是Object。 //可见doSome()方法无法接收基本数据类型的数字。那怎么办呢?可以传一个数字对应的包装类进去。 //把100这个数字经过构造方法包装成对象。 MyInt mi = new MyInt(100); //doSome()方法虽然不能直接传100,但是可以传一个100对应的包装类 doSome(mi); } public static void doSome(Object obj){ System.out.println(obj); } }
package integer; //这种包装类目前是我自己写的,实际开发中我们不需要自己再写。 //八种基本数据类型对应的八种包装类,SUN公司已经写好了。为我们直接用 public class MyInt { int value; public MyInt(){ } public MyInt(int value){ this.value = value; } @Override public String toString() { return String.valueOf(value); } }
-
八种包装类的名字
package integer; /* 1、八种基本数据类型对应的包装类型名是什么? ------------------------------------------ byte java.lang.Byte(父类:Number) short java.lang.Short(父类:Number) int java.lang.Integer(父类:Number) long java.lang.Long(父类:Number) float java.lang.Float(父类:Number) double java.lang.Double(父类:Number) boolean java.lang.Boolean(父类:Object) char java.lang.Character(父类:Object) 2、以上八种包装类,重点以java.lang.Integer为代表进行学习,其他的类型照葫芦画瓢就可以。 3、八种包装类中其中六个都是数字对应的包装类,他们的父类都是Number,可以先研究一下Number中的公共方法: Number是一个抽象类 ,无法实例化对象。 Number类中有这样的方法: byte byteValue() 以 byte 形式返回指定的数值 abstract double doubleValue() 以 double 形式返回指定数字的值 abstract float floatValue() 以 float 形式返回指定数字的值 abstract int intValue() 以 int 返回指定数字的值 abstract long longValue() 以 long 返回指定数字的值 short shortValue() 以 short 形式返回指定数字的值 这些方法其实所有的数字包装类的子类都有,这些方法是负责拆箱的。 */ public class IntegerText02 { public static void main(String[] args) { //123这个基本数据类型,进行构造方法的包装达到了:基本数据类型向引用数据类型的转换 //基本数据类型---转换-->引用数据类型(装箱) Integer i = new Integer(123); //将引用数据类型--转换-->基本数据类型(拆箱) float f = i.floatValue();//i对象调用floatValue方法返回float值后接收。 System.out.println(f); //将引用数据类型--转换-->基本数据类型(拆箱) int retValue = i.intValue(); System.out.println(retValue); } }
-
包装类的构造方法
package integer; /* 关于Integer类的构造方法有两个 */ public class integerText03 { public static void main(String[] args) { //java9之后不建议使用这个构造方法了。出现横线表示已过时。 //将数字100转成Integer包装类型(int--->Integer) Integer x = new Integer(100); System.out.println(x.toString()); //将String类型的数字,转成Integer包装类型(String--->Integer) Integer y = new Integer("123"); System.out.println(y); //Double类的构造方法 //double--->Double Double d = new Double(1.23); System.out.println(d); //String -->Double Double d2 = new Double("3.14"); System.out.println(d2); } }
-
通过访问包装类的常量,来获取最大值和最小值
package integer; public class IntegerText04 { public static void main(String[] args) { //通过访问包装类的常量,来获取最大值和最小值 System.out.println("int的最大值:"+Integer.MAX_VALUE); System.out.println("int的最小值:"+Integer.MIN_VALUE); System.out.println("byte的最大值:"+Byte.MAX_VALUE); System.out.println("byte的最小值:"+Byte.MIN_VALUE); } }
-
自动装箱,自动拆箱
package integer; //在JDK1.5之后,支持自动拆箱和自动装箱了。 public class IntegerText05 { public static void main(String[] args) { //900是基本数据类型 x是包装类型 //基本数据类型--自动转换-->包装类型 自动装箱 Integer x = 900; System.out.println(x); //x是包装类型 y是基本数据类型 //包装类型--自动转换-->基本数据类型 自动拆箱 int y = x; System.out.println(y); //z是一个引用,是一个变量,z还是保存了一个对象的内存地址。 Integer z = 1000; //等同于:Integer z = new Integer(1000); System.out.println(z+1); //分析为什么这个没有报错呢? //+两边要求是基本数据类型的数字,z是包装类,不属于基本数据类型,这里会进行自动拆箱,将z转换成基本数据类型 //在java5之前这样写,编译器报错。 Integer a = 1000; //Integer a = new Integer(1000);a是个引用,保存内存地址指向对象 Integer b = 1000; //Integer b = new Integer(1000);b是个引用,保存内存地址指向对象 //==比较的是对象的内存地址,a和b两个引用中保存的对象地址不同。 // == 这个运算符不会触发自动拆箱机制(只有 + - * / = 运算的时候才会) System.out.println(a == b);//false } }
-
Integer类的相关面试题
package integer; //这个是Integer非常重要的面试题。 public class IntegerText06 { public static void main(String[] args) { Integer a = 128; Integer b = 128; System.out.println(a == b);//false /* java中为了提高程序的执行效率,将[-128——127]之间的所有的包装对象提前创建好,放到了一个方法区的“整数型常量池”当中了, 目的是只要用这个区间的数据就不需要再new了,直接从整数型常量池中取出来。 原理:x变量中保存的对象的内存地址和y中保存的内存地址是一样的 */ Integer x = 127; Integer y = 127; //==永远判断两个兑现的内存地址是否相同 System.out.println(x == y);//true } }
-
Integer类当中常用的方法
package integer; /* 总结一下之前所学的经典异常: 空指针异常:NullPointerException 类型转换异常:ClassCastException 数组下标越界异常:ArrayIndexOutOfBoundsException 数字格式化异常:NumberFormatException Integer类当中有哪些常用的方法呢? */ public class IntegerText07{ public static void main(String[] args) { //intValue() //手动装箱 Integer x = new Integer(100); //手动拆箱 int y = x.intValue(); System.out.println(y); Integer a = new Integer("123"); //编译的时候没问题,一切符合java语法,运行时会不会出问题呢? //不是一个数字可以包装成Integer吗?不能 ,运行时出现异常。""里面只能是数字 //Integer b = new Integer("中文"); System.out.println(a); //重点方法 static int parseInt(Strings s) 静态方法,传参String 返回int //网页上文本框中输入100实际上是"100"字符串。后台数据库中要求存储数字类型的100,此时java程序要将"100"转换成100数字 int retValue = Integer.parseInt("112");//String --转换--> int System.out.println(retValue+138);//250 //照葫芦画瓢 double retValue2 = Double.parseDouble("3.14"); System.out.println(retValue2+1);//4.140000000000001 float retValue3 = Float.parseFloat("1.0"); System.out.println(retValue3+1);//2.0 //----------------以下内容作为了解,不需要掌握----------------------------- //static String toBinaryString(int i) 静态的:将十进制抓换成二进制 String binaryString = Integer.toBinaryString(3); System.out.println(binaryString);//"11" 二进制的字符串 //static String toHexString(int i) 静态的:将十进制转换成十六进制的字符串。 String hexString = Integer.toHexString(16); //10 System.out.println(hexString); System.out.println(Integer.toHexString(17)); //11 //static String toOctalString(int i) 静态的:将十进制转换成八进制的字符串 System.out.println(Integer.toOctalString(16)); //20 System.out.println(new Object());//java.lang.Object@1b6d3586 //valueOf方法作为了解 // static Integer valueOf(int i) 静态的:int--->Integer Integer i1 = Integer.valueOf(666); System.out.println(i1); // static Integer valueOf(String s) 静态的:String--->Integer Integer i2 = Integer.valueOf("999"); System.out.println(i2); } }
-
String、int、Integer之间的互相转换
package integer; //String int Integer之间互相转换 public class IntegerText08 { public static void main(String[] args) { //String ---> int int i1 = Integer.parseInt("100"); System.out.println(i1 +1);//101 //int ----> String String s2 = i1 +""; System.out.println(s2+1);//1001 //int ---> Integer Integer x = 1000; //自动装箱 //Integer -----> int int y = x; //自动拆箱 //String ----> Integer Integer k = Integer.valueOf("123"); //Integer ----> String String e = String.valueOf(k); } }
日期类Date
-
获取系统当前时间,以及对日期的格式化
package date; import java.text.SimpleDateFormat; import java.util.Date; /* java中对日期的处理 主要掌握:1、怎么获取系统当前时间 2、String ----> Date 3、Date -----> String */ //java中对日期的处理 public class DateText01 { public static void main(String[] args) throws Exception{ //获取当前时间(精确到毫秒的系统当前时间) //直接调用无参数构造方法 Date nowTime = new Date(); //java.util.Date类的toString()方法已经被重写了。 //输出的应该不是一个对象的内存地址,应该是一个日期字符串。 System.out.println(nowTime); //Sat Jan 16 17:55:05 CST 2021 星期六 一月16 17:55:05 国际标准时间 2021年 //日期可以格式化吗 //将日期类型Date ,按照指定的格式进行转换:Date --->转换成具有一定格式的字符串-->String //SimpleDateFormat 是java.text包下的,专门负责日期格式化的。 /* yyyy 年 年是4位 MM 月 月是2位 dd 日 日是2位 HH 时 2位 mm 分 2位 ss 秒 2位 SSS 毫秒 3位(最高999,1000毫秒代表一秒) 注意:在日期格式中,除了y M d H m s S 这些字符不能随便写之外,剩下的符号格式自己随意组织 */ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); // SimpleDateFormat sdf2 = new SimpleDateFormat("dd/MM/yyyy"); // SimpleDateFormat sdf3 = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); String nowTimeStr = sdf.format(nowTime); System.out.println(nowTimeStr); //假设现在有一个日期字符串String 怎么转换为Date类型? //String ------> Date String time = "2008-08-08 08:08:08 888"; // SimpleDateFormat sdf2 = new SimpleDateFormat("格式不能随便写,要和日期字符串格式相同"); //注意:字符串的日期格式和SimpleDateFormat对象指定的日期格式要一致,不然会出现:java.text.ParseException异常 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); Date dateTime = sdf2.parse(time); System.out.println(dateTime); //Fri Aug 08 08:08:08 CST 2008 } }
-
获取自1970年1月1日 00:00:00 000 到当前系统时间的总毫秒数,以及统计一个方法执行所耗时长
package date; /*获取自1970年1月1日 00:00:00 000 到当前系统时间的总毫秒数。 1秒 = 1000 毫秒 简单统计一下System类的相关属性和方法: System.out 【out是System类的静态变量】 System.out.println() 【println()方法不是System类的,是printStream类的方法】 System.gc() 建议启动垃圾回收器 System.currentTimeMillis() 获取自1970年1月1日到系统当前时间的总毫秒数 System.exit(0) 退出JVM */ public class DaTeText02 { public static void main(String[] args) { long nowTimeMillis = System.currentTimeMillis(); System.out.println(nowTimeMillis);//1610863950844 //统计一个方法耗时 //在调用目标方法之前记录一个毫秒数 long begin = System.currentTimeMillis(); print(); //在执行完目标方法之后记录一个毫秒数 long end = System.currentTimeMillis(); System.out.println("耗费时长:"+(end-begin)+"毫秒"); } //需求:统计一个方法执行所耗费的时长 public static void print(){ for(int i = 0 ; i<100000 ;i++){ System.out.println("i ="+i); } } }
-
Date的参数
package date; import java.text.SimpleDateFormat; import java.util.Date; public class DateText03 { public static void main(String[] args) { //这个时间是什么时间? //1970-01-01 00:00:00 001 Date time = new Date(1);//注意:参数是一个毫秒 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); //北京是东8区,差八个小时。 System.out.println(sdf.format(time));//1970-01-01 08:00:00 001 //获取昨天的此时的时间 Date time2 = new Date(System.currentTimeMillis() - 1000*60*60*24); System.out.println(sdf.format(time2));//2021-01-16 16:32:14 315 //获取去年的今天的时间 Date time3 = new Date(System.currentTimeMillis() - 1000*60*60*24*365); System.out.println(sdf.format(time3)); } }
数字类
-
格式化数字
package number; import java.text.DecimalFormat; public class DecimalFormatText01 { public static void main(String[] args) { //java.text.DecimalFormat专门负责格式化的 //Decimal df = new DecimalFormat("数字格式") /* 数字格式有哪些 # 代表任意数字 , 代表千分位 . 代表小数点 0 代表不够时补0 ###,###.## 表示:加入千分位,保留两位小数 */ DecimalFormat df = new DecimalFormat("###,###.##"); System.out.println(df.format(1234.4));//1,234.4 System.out.println(df.format(6542.468));//6,542.47 System.out.println(df.format(546542.468));//546,542.47 System.out.println(df.format(52343446542.468));//52,343,446,542.47 DecimalFormat df2 = new DecimalFormat("###,###.0000");//保留4个小数位,不够补上0 System.out.println(df2.format(8766.9));//8,766.9000 System.out.println(df2.format(8766.93436));//8,766.9344 } }
-
专门用来处理财务数据的:BigDecimal
package number; import java.math.BigDecimal; /* 1、BigDecimal 属于大数据,精度极高。不属于基本数据类型,属于java对象(引用数据类型) 这是SUN提供的一个类,专门用在财务软件当中 2、注意:财务软件中,double是不够的。处理财务数据,用哪一种数据类型? 千万别说double,说java.math.BigDecimal */ public class BigDecimalText01 { public static void main(String[] args) { //这个100不是普通的100,是精度极高的100 BigDecimal bg = new BigDecimal(100); //精度极高的200 BigDecimal bg2 = new BigDecimal(200); //求和 //bg + bg2 这样不行,bg和bg2都是引用,不能直接使用+求和 BigDecimal bg3 = bg.add(bg2);//使用方法求和 System.out.println(bg3);//300 System.out.println(bg2.divide(bg));//2 } }
随机数
-
如何生成随机数
package random; import java.util.Random; //随机数 public class RandomText01 { public static void main(String[] args) { //创建随机数对象 Random random = new Random(); //随机产生一个int类型取值范围内的数字 int num1 = random.nextInt(); System.out.println(num1); //产生[0~100]之间的随机数,不能产生101 //nexInt翻译为:下一个int类型的数据是101,表示只能取到100 int num2 = random.nextInt(101);//不包括101 System.out.println(num2); } }
-
生成5个不重复的随机数[0~100],如果重复,则重新生成,然后放到数组当中,要求这5个随机数不能重复
package random; import java.util.Arrays; import java.util.Random; /* 编写程序,生成5个不重复的随机数[0~100],重复的话重新生成。 最终生成的5个随机数放到数组当中,要求数组中这5个随机数不重复 */ public class RandomText02 { public static void main(String[] args) { //创建随机数对象 Random random = new Random(); //定义一个长度为5的一维数组 int[] arr = new int[5]; //给数组中每个元素的默认值为-1。 for (int i = 0; i <arr.length ; i++) { arr[i] = -1; } //定义一个变量用来模拟数组下标 int index = arr.length-1; //因为还要判断是不是有重复的数字,用for循环次数比较固定,所以用while循环,里面再加判断 //在排序出现bug之后,采用倒序赋值。index为数组元素下标,从最后一个开始赋,下标为:数组长度-1 while( index >= 0){//下标<数组长度,为每一个元素赋值,如生成的数字与已经放入的重复,则赋值失败,再次循环,直到数组中每个元素都不相同 //生成随机数 int num = random.nextInt(101);// [0-100]范围有点大。 // int num = random.nextInt(6);// 只能生成[0-5]的随机数 // int num = random.nextInt(4);// 只能生成[0-3]的随机数 //当数组长度大于可生成的随机数范围(不能重复)时,会进入死循环 System.out.println("生成的随机数:"+num); //判断arr数组中有没有这个num,如果没有的话,再放进去,如果有,则不执行赋值操作以及数组下标+1// //从后面开始赋,修改为数组下标-1。 //if(数组中不包含这个num){赋值,赋值后index要加1,再次循环时为下一个数组元素放入数}//赋值后-1 if(!contains(arr,num)){//contains方法返回一个布尔值,为true时包含,如果包含,则不执行。所以取非运算 // arr[index] = num; // index++; //合并:赋值后,index+1,然后进行下一次循环。属于赋值后才+1,++运算符可以写在后面//修改为-1. arr[index--] = num; } } for (int i = 0; i <arr.length ; i++) { System.out.println(arr[i]); } } /** * 单独编写一个方法,这个方法专门用来判断数组中是否包含某个元素 * @param arr 数组 * @param key 元素 * @return true表示包含,false表示不包含 */ public static boolean contains(int[] arr,int key){ /* //先对数组进行排序 Arrays.sort(arr); //使用二分法进行查找 二分法查找的结果 >=0说明:这个元素找到了,找到了表示存在! return Arrays.binarySearch(arr,key) >= 0; 这个写法有bug:每当一个值进去,就会重新排一次顺序,如:arr[0]经过循环赋上值后,经过排序:这个值就排在了最后一位, 然后为第二个元素赋值,第二个赋上值之后也排在了后面。然后为第三个赋值,为第四个第五个赋值时,这里已经是赋值了的三个元素中的两个。 所以第一个第二个元素永远赋不上值,永远都是-1. */ Arrays.sort(arr); return Arrays.binarySearch(arr,key) >= 0; //如果从数组下标为0开始放入数据,则使用以下方法判断是否包含,以避免重复 /*或者使用for循环判断是否包含。 for (int i = 0; i <arr.length ; i++) { if(arr[i] == key){ return true;//判断是否有相同,如相同,则发生包含。 } //反之,不包含 return false; } */ } }
枚举
-
枚举的引出
package enum0; //标识符,关键字不能做标识符,enum是关键字 /* 分析以下程序,在设计方面有什么缺陷? 以下代码可以编译,也可以运行。只是设计上有些缺陷 */ public class EnumText01 { public static void main(String[] args) { //System.out.println(10/0); //java.lang.ArithmeticException: / by zero 被0除,除数为0了 /* int retValue = divide(10,2); System.out.println(retValue);//1 int retValue2 = divide(10,0); System.out.println(retValue2);//0*/ boolean success = divide(10,2); System.out.println(success?"计算成功":"计算失败"); boolean success2 = divide(10,0); System.out.println(success2?"计算成功":"计算失败"); } /** * 需求(这是设计者说的):以下程序,计算两个int类型数据的商,计算成功返回1 ,计算失败返回0! * @param a int类型的数据 * @param b int类型的数据 */ /* public static int divide(int a ,int b){ try { int c = a / b; //程序执行到这里表示以上代码没有发生异常。表示执行成功。 return 1; } catch(Exception e) { //程序执行到这里表示以上程序出现了异常,表示执行失败 return 0 ; } }*/ //设计缺陷:在这个方法的返回值上,返回一个int不恰当。 // 既然最后的结果只是成功和失败,最好使用布尔类型。因为布尔类型true和false正好可以表示两种不同的状态 /* public static int divide(int a ,int b){ try { int c = a / b; //有可能这里一个失误,返回了10,已经偏离了需求,但是编译器没有检查出来。我们一直想追求的是:所有的错误尽可能让编译器找出来,所有的错误越早发现越好 return 1; } catch(Exception e) { //程序执行到这里表示以上程序出现了异常,表示执行失败 return 0 ; } }*/ //这种设计就很不错 public static boolean divide(int a ,int b){ try { int c = a / b; return true; } catch (Exception e){ return false; } } /* 思考:以上这个方法的设计很好,返回true和false两种情况,但是在以后的开发中,有可能遇到一个方法的执行结果可能包括三种情况,四种情况 五种情况不等。但是每一个都是可以数清楚的,一枚一枚都是可以列举出来的。这时布尔类型就无法满足需求了,此时需要使用java语言中的枚举类型 */ }
-
枚举的使用
package enum0; //采用枚举的方式改造程序 /* 总结: 1、枚举是一种引用类型数据 2、枚举类型怎么定义,语法是? enum 枚举类型名{ 枚举值1,枚举值2...... } 3、结果只有两种情况的,建议使用布尔类型。结果超出两种并且还是可以一枚一枚列举出来的,建议使用枚举类型。 例如:颜色、四季、星期等都可以使用枚举类型。 */ public class EnumText02 { public static void main(String[] args) { Result r = divide(10,2); System.out.println(r == Result.SUCCESS ? "计算成功":"计算失败"); } /** * 计算两个int类型数据的商 * @param a int类型的数据 * @param b int类型的数据 * @return Result.SUCCESS 表示成功 Result.FAIL表示失败! */ public static Result divide(int a,int b){ try{ int c = a / b; return Result.SUCCESS; }catch (Exception e){ return Result.FAIL; } } } //枚举:一枚一枚可以列举出来的,才建议使用枚举类型 //枚举编译之后也是生成class文件,枚举也是一种引用数据类型。枚举中的每一个值可以看作是常量 enum Result{ //SUCCESS 是枚举Result类型中的一个值 //FAIL 是枚举Result类型中的一个值 //枚举中的每一个值,可以看作是“常量” SUCCESS,FAIL }
四季枚举类型
package enum0; //四季枚举类型 public enum Season { //春夏秋冬 SPRING,SUMMER,AUTUMN,WINTER }
颜色枚举类型
package enum0; //颜色枚举类型 public enum Color { //春夏秋冬 RED,GREEN,GOLD,GREEY,WRITE,BLACK }
-
switch语句支持枚举类型
package enum0; import static enum0.Season.SPRING; public class SwitchText { public static void main(String[] args) { //switch语句支持枚举类型 //switch也支持String、int。 //低版本的JDK,只支持int 高版本的JDK,支持int、String、枚举 //byte、short、char也可以,因为存在自动类型转换。 switch (Season.WINTER){ case SPRING: System.out.println("春天"); break; case SUMMER: System.out.println("夏天"); break; case AUTUMN: System.out.println("秋天"); break; case WINTER: System.out.println("冬天"); break; } } }