美文网首页
Java学习笔记六:常用类

Java学习笔记六:常用类

作者: 开发者连小超 | 来源:发表于2020-01-14 21:53 被阅读0次

    一、 包装类

    (1)包装类概述

    Java是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。但是我们在实际应用中经常需要将基本数据转化成对象,以便于操作。比如:将基本数据类型存储到Object[]数组或集合中的操作等等。
    为了解决这个不足,Java在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。


    基本数据类型对应的包装类.png

    在这八个类中,除了Character和Boolean以外,其他的都是“数字型”,“数字型”都是java.lang.Number的子类。Number类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的“数字型”包装类都可以互相转型。

    (2)自动装箱和拆箱

    自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的互相转换。JDK1.5后,Java引入了自动装箱(autoboxing)/拆箱(unboxing)。

    • 自动装箱
      基本类型的数据处于需要对象的环境中时,会自动转为“对象”。以Integer为例:JDK1.5以后,Java提供了自动装箱的功能,因此只需Integer i = 5这样的语句就能实现基本数据类型转换成包装类,这是因为JVM为我们执行了Integer i = Integer.valueOf(5)这样的操作,这就是Java的自动装箱。
    Integer i = 100;//自动装箱
    //相当于编译器自动为您作以下的语法编译:
    Integer i = Integer.valueOf(100);//调用的是valueOf(100),而不是new Integer(100)
    
    • 自动拆箱
      每当需要一个值时,对象会自动转成基本数据类型,没必要再去显式调用intValue()、doubleValue()等转型方法。如 Integer i = 5;int j = i; 这样的过程就是自动拆箱。
    Integer i = 100;
    int j = i;//自动拆箱
    //相当于编译器自动为您作以下的语法编译:
    int j = i.intValue();
    
    • 总结
      自动装箱过程是通过调用包装类的valueOf()方法实现的,而自动拆箱过程是通过调用包装类的 xxxValue()方法实现的(xxx代表对应的基本数据类型,如intValue()、doubleValue()等)。
      整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。
    (3)包装类的缓存问题

    缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

    public class Test3 {
        public static void main(String[] args) {
            Integer in1 = -128;
            Integer in2 = -128;
            System.out.println(in1 == in2);//true 因为123在缓存范围内
            System.out.println(in1.equals(in2));//true
            Integer in3 = 1234;
            Integer in4 = 1234;
            System.out.println(in3 == in4);//false 因为1234不在缓存范围内
            System.out.println(in3.equals(in4));//true
        }
    }
    

    二、 String类

    (1)String

    String 类对象代表不可变的Unicode字符序列,因此我们可以将String对象称为“不可变对象”。 那什么叫做“不可变对象”呢?指的是对象内部的成员变量的值无法再改变。
    substring()是对字符串的截取操作,但本质是读取原字符串内容生成了新的字符串

    public class TestString1 {
        public static void main(String[] args) {
            String s1 = new String("abcdef");
            String s2 = s1.substring(2, 4);
            // 打印:ab199863
            System.out.println(Integer.toHexString(s1.hashCode()));
            // 打印:c61, 显然s1和s2不是同一个对象
            System.out.println(Integer.toHexString(s2.hashCode()));
        }
    }
    

    在遇到字符串常量之间的拼接时,编译器会做出优化,即在编译期间就会完成字符串的拼接。因此,在使用==进行String对象之间的比较时,我们需要特别注意

    public class TestString2 {
        public static void main(String[] args) {
            //编译器做了优化,直接在编译的时候将字符串进行拼接
            String str1 = "hello" + " java";//相当于str1 = "hello java";
            String str2 = "hello java";
            System.out.println(str1 == str2);//true
            String str3 = "hello";
            String str4 = " java";
            //编译的时候不知道变量中存储的是什么,所以没办法在编译的时候优化
            String str5 = str3 + str4;
            System.out.println(str2 == str5);//false
        }
    }
    

    String类常用的方法有:
    1.String类的下述方法能创建并返回一个新的String对象: concat()、 replace()、substring()、 toLowerCase()、 toUpperCase()、trim()。
    2.提供查找功能的有关方法: endsWith()、 startsWith()、 indexOf()、lastIndexOf()。
    3.提供比较功能的方法: equals()、equalsIgnoreCase()、compareTo()。
    4.其它方法: charAt() 、length()。

    (2)StringBuffer和StringBuilder

    StringBuffer和StringBuilder非常类似,均代表可变的字符序列。 这两个类都是抽象类AbstractStringBuilder的子类,方法几乎一模一样。StringBuilder和StringBuffer称之为“可变字符序列”。那两者有什么区别呢?
    1.StringBuffer JDK1.0版本提供的类,线程安全,做线程同步检查, 效率较低。
    2.StringBuilder JDK1.5版本提供的类,线程不安全,不做线程同步检查,因此效率较高。 建议采用该类。

    • 常用方法列表:
      1.重载的 public StringBuilder append()
      可以为该StringBuilder 对象添加字符序列,仍然返回自身对象。
      2.public StringBuilder delete(int start,int end)
      可以删除从start开始到end-1为止的一段字符序列,仍然返回自身对象。
      3.public StringBuilder deleteCharAt(int index)
      移除此序列指定位置上的 char,仍然返回自身对象。
      4.重载的 public StringBuilder insert(…)
      可以为该StringBuilder 对象在指定位置插入字符序列,仍然返回自身对象。
      5.public StringBuilder reverse()
      用于将字符序列逆序,仍然返回自身对象。
      6. public String toString()
      7. 和 String 类含义类似的方法:
    public int indexOf(String str)
    public int indexOf(String str,int fromIndex)
    public String substring(int start)
    public String substring(int start,int end)
    public int length() 
    char charAt(int index)
    
    (3) String使用的陷阱

    String一经初始化后,就不会再改变其内容了。对String字符串的操作实际上是对其副本(原始拷贝)的操作,原来的字符串一点都没有改变。比如:String s ="a"; 创建了一个字符串,s = s+"b"
    实际上原来的"a"字符串对象已经丢弃了,现在又产生了另一个字符串s+"b"(也就是"ab")
    如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的时间和空间性能,甚至会造成服务器的崩溃。
    相反,StringBuilder和StringBuffer类是对原字符串本身操作的,可以对字符串进行修改而不产生副本拷贝或者产生少量的副本。因此可以在循环中使用。

    public class Test {
        public static void main(String[] args) {
            /**使用String进行字符串的拼接*/
            String str8 = "";
            //本质上使用StringBuilder拼接, 但是每次循环都会生成一个StringBuilder对象
            long num1 = Runtime.getRuntime().freeMemory();//获取系统剩余内存空间
            long time1 = System.currentTimeMillis();//获取系统的当前时间
            for (int i = 0; i < 5000; i++) {
                str8 = str8 + i;//相当于产生了10000个对象
            }
            long num2 = Runtime.getRuntime().freeMemory();
            long time2 = System.currentTimeMillis();
            System.out.println("String占用内存 : " + (num1 - num2));
            System.out.println("String占用时间 : " + (time2 - time1));
            /**使用StringBuilder进行字符串的拼接*/
            StringBuilder sb1 = new StringBuilder("");
            long num3 = Runtime.getRuntime().freeMemory();
            long time3 = System.currentTimeMillis();
            for (int i = 0; i < 5000; i++) {
                sb1.append(i);
            }
            long num4 = Runtime.getRuntime().freeMemory();
            long time4 = System.currentTimeMillis();
            System.out.println("StringBuilder占用内存 : " + (num3 - num4));
            System.out.println("StringBuilder占用时间 : " + (time4 - time3));
        }
    }
    
    (4) Java字符串格式化
    JAVA字符串格式化.png

    三、 时间处理相关类

    在计算机世界,我们把1970 年 1 月 1 日 00:00:00定为基准时间,每个度量单位是毫秒(1秒的千分之一)。我们用long类型的变量来表示时间,从基准时间往前几亿年,往后几亿年都能表示。如果想获得现在时刻的“时刻数值”,可以使用:long now = System.currentTimeMillis();

    日期时间相关类.png
    (1)Date时间类(java.util.Date)
    public class TestDate {
        public static void main(String[] args) {
            Date date1 = new Date();
            System.out.println(date1.toString()); //Tue Jan 14 21:12:39 CST 2020
            long i = date1.getTime();
            Date date2 = new Date(i - 1000);
            Date date3 = new Date(i + 1000);
            System.out.println(date1.after(date2));//true 测试此日期是否在指定日期之后
            System.out.println(date1.before(date2));//false 测试此日期是否在指定日期之前。
            System.out.println(date1.equals(date2));//false 比较两个日期的相等性。
            System.out.println(date1.before(date3));//true
            System.out.println(date1.after(date3));//false
            System.out.println(date1.equals(date3));//false
            System.out.println(new Date(1000L * 60 * 60 * 24 * 365 * 39L).toString());//Mon Dec 22 08:00:00 CST 2008
        }
    }
    
    (2)DateFormat类和SimpleDateFormat类
    • DateFormat类的作用
      把时间对象转化成指定格式的字符串。反之,把指定格式的字符串转化成时间对象。DateFormat是一个抽象类,一般使用它的的子类SimpleDateFormat类来实现。
    public void test() throws ParseException {
            SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            SimpleDateFormat s2 = new SimpleDateFormat("yyyy-MM-dd");
            // 将时间对象转换成字符串
            String daytime = s1.format(new Date());
            System.out.println(daytime); //2020-01-14 09:18:28
            System.out.println(s2.format(new Date()));//2020-01-14
            System.out.println(new SimpleDateFormat("hh:mm:ss").format(new Date())); //09:18:28
            
            String time = "2007-10-7";
            Date date = s2.parse(time);
            System.out.println("date1: " + date); //date1: Sun Oct 07 00:00:00 CST 2007
            
            time = "2007-10-7 20:15:30";
            date = s1.parse(time);
            System.out.println("date2: " + date); //date2: Sun Oct 07 20:15:30 CST 2007
        }
    }
    

    获得当前时间是今年的第几天

    public class TestDateFormat2 {
        public static void main(String[] args) {
            SimpleDateFormat s1 = new SimpleDateFormat("D");
            String daytime = s1.format(new Date());
            System.out.println(daytime);
        }
    }
    
    图片.png
    (3)Calendar日历类

    Calendar 类是一个抽象类,为我们提供了关于日期计算的相关功能,比如:年、月、日、时、分、秒的展示和计算。GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统。

    // 设置日期
    GregorianCalendar calendar2 = new GregorianCalendar();
    calendar2.set(Calendar.YEAR, 2999);
    calendar2.set(Calendar.MONTH, Calendar.FEBRUARY); // 月份数:0-11
    calendar2.set(Calendar.DATE, 3);
    calendar2.set(Calendar.HOUR_OF_DAY, 10);
    calendar2.set(Calendar.MINUTE, 20);
    calendar2.set(Calendar.SECOND, 23);
    
    // 日期计算
    GregorianCalendar calendar3 = new GregorianCalendar(2999, 10, 9, 22, 10, 50);
    calendar3.add(Calendar.MONTH, -7); // 月份减7
    calendar3.add(Calendar.DATE, 7); // 增加7天
    

    四、 Math类

    java.lang.Math提供了一系列静态方法用于科学计算;其方法的参数和返回值类型一般为double型。如果需要更加强大的数学运算能力,计算高等数学中的相关内容,可以使用apache commons下面的Math类库。

    public void test(){
        //取整相关操作
        System.out.println(Math.ceil(3.2));//4.0
        System.out.println(Math.floor(3.2));//3.0
        System.out.println(Math.round(3.2));//3
        System.out.println(Math.round(3.8));//4
        //绝对值、开方、a的b次幂等操作
        System.out.println(Math.abs(-45));//45
        System.out.println(Math.sqrt(64));//8.0
        System.out.println(Math.pow(5, 2));//25.0
        System.out.println(Math.pow(2, 5));//32.0
        //Math类中常用的常量
        System.out.println(Math.PI);//3.141592653589793
        System.out.println(Math.E);//2.718281828459045
        //随机数
        System.out.println(Math.random());// [0,1) 0.15899707596998602
        }
    }
    

    Random类使用

    public class TestRandom {
        public static void main(String[] args) {
            Random rand = new Random();
            //随机生成[0,1)之间的double类型的数据
            System.out.println(rand.nextDouble());
            //随机生成int类型允许范围之内的整型数据
            System.out.println(rand.nextInt());
            //随机生成[0,1)之间的float类型的数据
            System.out.println(rand.nextFloat());
            //随机生成false或者true
            System.out.println(rand.nextBoolean());
            //随机生成[0,10)之间的int类型的数据
            System.out.print(rand.nextInt(10));
            //随机生成[20,30)之间的int类型的数据
            System.out.print(20 + rand.nextInt(10));
            //随机生成[20,30)之间的int类型的数据(此种方法计算较为复杂)
            System.out.print(20 + (int) (rand.nextDouble() * 10));
        }
    }
    

    五、 File类

    java.io.File类:代表文件和目录。 在开发中,读取文件、生成文件、删除文件、修改文件的属性时经常会用到本类。

    文件的创建

    import java.io.File;
    public class TestFile1 {
        public static void main(String[] args) throws Exception {
            System.out.println(System.getProperty("user.dir")); //本项目的目录
            File f = new File("a.txt"); //相对路径:默认放到user.dir目录下面
            f.createNewFile();//创建文件
            File f2 = new File("d:/b.txt");//绝对路径
            f2.createNewFile();
        }
    }
    

    File类访问属性的基本用法

    public class TestFile2 {
        public static void main(String[] args) throws Exception {
            File f = new File("d:/b.txt");
            System.out.println("File是否存在:"+f.exists());
            System.out.println("File是否是目录:"+f.isDirectory());
            System.out.println("File是否是文件:"+f.isFile());
            System.out.println("File最后修改时间:"+new Date(f.lastModified()));
            System.out.println("File的大小:"+f.length());
            System.out.println("File的文件名:"+f.getName());
            System.out.println("File的目录路径:"+f.getPath());
        }
    }
    

    使用mkdir创建目录

    public class TestFile5 {
        public static void main(String[] args) {
            //指定一个文件
            File file = new File("d:/sxt/b.txt");
            //判断该文件是否存在
            boolean flag= file.exists();
            //如果存在就删除,如果不存在就创建
            if(flag){
                //删除
                boolean flagd = file.delete();
                if(flagd){
                    System.out.println("删除成功");
                }else{
                    System.out.println("删除失败");
                }
            }else{
                //创建
                boolean flagn = true;
                try {
                    //如果目录不存在,先创建目录
                    File dir = file.getParentFile();
                    dir.mkdirs();
                    //创建文件
                    flagn = file.createNewFile();
                    System.out.println("创建成功");
                } catch (IOException e) {
                    System.out.println("创建失败");
                    e.printStackTrace();
                }          
            }
            //文件重命名(同学可以自己测试一下)
            //file.renameTo(new File("d:/readme.txt"));
        }
    }
    

    相关文章

      网友评论

          本文标题:Java学习笔记六:常用类

          本文链接:https://www.haomeiwen.com/subject/fxuaactx.html