DAY11

Object

Object类是所有Java类的祖先,也就是说我们所说的”顶级父类”
存在于java.lang.Object,这个包不需要我们手动导包
每个类都使用Object作为超类.所有对象(包括数组)都实现这个类的方法.在不明确给出超类的情况下,Java会自动把Object类作为要定义类的超类.

常用方法介绍

toString()
本方法用于返回对应对象的字符串表示.
hashCode()
本方法用于返回对应对象的哈希码值
equals()
本方法用于指示其他某个对象是否与当前对象”相等”

练习1:Object类练习

  1. /**本类用于测试Object类的使用*/
  2. //总结:
  3. //1.如果想要查看对象的属性值,需要重写toString(),否则会使用Object的默认实现,打印对象的地址值
  4. //2.如果要判断两个对象间的所有属性值相同,比较完的结果返回true,需要重写equlas(),否则会使用Object类的默认实现,==比较
  5. public class Test1_Object {
  6. public static void main(String[] args) {
  7. /**测试toString():返回该对象的字符串表示*/
  8. //3.创建Student对象
  9. Student s = new Student("jack",18);
  10. //4.打印学生对象,查看属性值是否赋值成功
  11. //第一次测试:打印结果:cn.tedu.api.Student@15db9742,s对象的地址值
  12. /**查看源码的方式:按住Ctrl键,鼠标移动到目标上即可*/
  13. //原因:在打印对象的s时,底层会自动调用Object类中的toString(),本来的实现方式就是打印地址值
  14. //public String toString() {return getClass.getName() + "@" +Integer.toHexString(hashCode());}
  15. //6.再次打印学生对象s
  16. //第二次测试:结果:Student [name=jack, age=18]
  17. //原因:重写了Object的toString()后,就可以打印对象的属性值了
  18. System.out.println(s);
  19. /**测试hashCode():返回对象在内存中的哈希码值*/
  20. //7.调用下查看hashCode()的结果
  21. System.out.println(s.hashCode());//366712642
  22. //8.创建对象s2与s对象属性值相同
  23. Student s2 = new Student("jack",18);
  24. //第一次测试:结果:false
  25. //底层:用了==进行对象间的比较,==比较的是两个对象的地址值,s与s2是两个对象.地址值不同,所以返回false
  26. //public boolean equals(Object obj) {return (this == obj);}
  27. //需求:比较s和s2对象,如果属性值相同,就认为是用一个对象,并让equals()返回true
  28. //第二次测试:结果:true
  29. System.out.println(s.equals(s2));
  30. }
  31. }
  32. //1.创建Student类并定义属性
  33. class Student{
  34. String name;
  35. int age;
  36. //2.生成构造方法
  37. //方式一:右键,选择Source,选择Generate Constructor using fields
  38. //方式二:Alt+shift+s,选倒数第三个
  39. public Student() {}//添加了含参构造后,记得手动添加无参构造
  40. public Student(String name, int age) {
  41. super();
  42. this.name = name;
  43. this.age = age;
  44. }
  45. //5.重写toString(),查看对象的属性值,否则会使用Objetc中的默认实现,查看对象的地址值
  46. //方式一:右键,选择Source,选择Generate toString()...
  47. //方式二:Alt+shift+s,选倒数第四个
  48. @Override
  49. public String toString() {
  50. return "Student [name=" + name + ", age=" + age + "]";
  51. }
  52. //9.重写equlas()
  53. //需求:比较s和s2对象,如果属性值相同,就认为是用一个对象,并让equals()返回true
  54. //自己写的
  55. public boolean equals2(Object obj) {
  56. //判断,如果是学生,咱俩比较,如果连学生都不是,就返回false--匹配种类
  57. if(obj instanceof Student) {//同一个类型的对象间比较
  58. //把obj强转成Student类型,因为想用子类的特有属性,如果不转,只能用父类的属性
  59. Student argsStudent = (Student)obj;
  60. //判断:如果当前对象this和参数对象argsStudent,他们的属性&属性值完全一样,就返回true
  61. if(this.name == argsStudent.name && this.age == argsStudent.age) {
  62. return true;
  63. }
  64. }
  65. return false;
  66. }
  67. //自动生成equlas()
  68. //方式一:右键,选择Source,选择Generate hashCode()... and equlas()
  69. //方式二:Alt+shift+s,选倒数第五个
  70. @Override
  71. public boolean equals(Object obj) {
  72. if (this == obj)
  73. return true;
  74. if (obj == null)
  75. return false;
  76. if (getClass() != obj.getClass())
  77. return false;
  78. Student other = (Student) obj;
  79. if (age != other.age)
  80. return false;
  81. if (name == null) {
  82. if (other.name != null)
  83. return false;
  84. } else if (!name.equals(other.name))
  85. return false;
  86. return true;
  87. }
  88. }

String

特点

String是一个封装char[]数组的对象,字符串不可变
通过下图中的底层实现可以看出:被final修饰,是常量
String str = “abc”; 等效于:char data[] = {‘a’, ‘b’, ‘c’};

常见方法

length()-查看字符串的长度
charAt()—定位某个字符,返回它的位置
concat()在原有的字符串上进行拼接,注意不改变原来的串
IndexOf()-某个字符开始一次出现的位置
lastIndexOf()-某个字符最后一次出现的位置
substring()-截取子串,如果参数有两个左闭右开[1,5)
equals()-判断两个串是否相等,注意String重写了Object的此方法,所以内容相同就返回true
startsWith()-判断是不是以参数开头
endsWith()—判断是不是以参数结尾
split()—以指定字符分割
trim()-去掉首尾两端的空格
getBytes()-把串转换成数组
toUpperCase()-变成全大写
toLowerCase()-变成全小写
String.valueOf(10)-把int类型的10转换成String类型

StringBuilder/StringBuffer

特点

  1. 封装了char[]数组
    2. 是可变的字符序列
    3. 提供了一组可以对字符内容修改的方法
    4. 常用append()来代替字符串做字符串连接”+”
    5.StringBuffer 1.0出道线程安全,StringBuilder1.5出道线程不安全

常见方法

append()

正则表达式练习:测试输入身份证号

  1. import java.util.Scanner;
  2. /**本类用于测试正则表达式
  3. * 需求:测试输入身份证号,测试用户输入是否正确
  4. * */
  5. public class Test4_Regex {
  6. public static void main(String[] args) {
  7. //1.提示并接收用户输入的身份证号:
  8. System.out.println("请您输入您的身份证号:");
  9. String input = new Scanner(System.in).nextLine();
  10. //2.编辑正则表达式
  11. //身份证号的规律:一般都是18位,前17位都是数字,最后一位可能是数字,也有可能是xX
  12. String regex = "[0-9]{17}[0-9xX]";
  13. //3.判断,是否符合正则表达式的规则(也就是输入的是正确的身份证号吗?)
  14. if( input.matches(regex) ) {//matches()是String类提供的功能,可以用来判断字符串是否符合正则表达式的要求
  15. System.out.println("输入正确!");
  16. }else {
  17. System.out.println("输入不正确,请重新输入!");
  18. }
  19. }
  20. }

包装类

创建对象
Integer
1. new Integer(5);
2. Integer.valueOf(5);
在Integer类中,包含256个Integer缓存对象,范围是 -128到127。
使用valueOf()时,如果指定范围内的值,访问缓存对象,而不新建;如果指定范围外的值,直接新建对象。

double
1. new Double(3.14)
2. Double.valueOf(3.14)//和 new 没有区别

常见方法

Integer
static int parseInt(String s) **将字符串参数作为有符号的十进制整数进行解析**

double
Double.parseDouble();

自动装箱和自动拆箱

概述

自动装箱:把 基本类型 包装成对应的 包装类型 的过程
Integer a = 5;//a是引用类型,引用了包装对象的地址。
编译器会完成对象的自动装箱:Integer a = Integer.valueOf(5);

自动拆箱:从包装类型的值,自动变成 基本类型的值
int i = a;//a现在是包装类型,没法给变量赋值,需要把5取出来。

练习6: 自动装箱与自动拆箱测试

  1. /**本类用来测试自动装箱与自动拆箱*/
  2. public class Test6_Box {
  3. public static void main(String[] args) {
  4. //1.定义包装类型的数据
  5. //之前的方式:创建包装类型的两种方式:
  6. Integer i11 = new Integer(127);
  7. Integer i22 = Integer.valueOf(127);
  8. //现在的方式:
  9. /**1.自动装箱:编译器会自动把基本类型int数据5,包装成包装类型Integer,然后交给i1保存
  10. * 自动装箱底层发生的代码:Integer.valueOf(5);
  11. * valueOf()的方向:int --> Interger
  12. * */
  13. Integer i1 = 5;//不会报错,这个现象就是自动装箱
  14. /**2.自动拆箱:编译器会自动把包装类型的5,拆掉箱子,变回到基本类型数据5
  15. * 自动拆箱底层发生的代码:i1.intValue()
  16. * intValue()的方向:Integer --> int
  17. * */
  18. int i2 = i1;//不会报错,这个现象就是自动拆箱
  19. }
  20. }

==和equals的区别

1.当使用==比较时,如果相比较的两个变量是引用类型,那么比较的是两者的物理地值(内存地址),如果相比较的两个变量都是数值类型,那么比较的是具体数值是否相等。
2.当使用equals()方法进行比较时,比较的结果实际上取决于equals()方法的具体实现
众所周知,任何类都继承自Object类,因此所有的类均具有Object类的特性,比如String、integer等,他们在自己的类中重写了equals()方法,此时他们进行的是数值的比较,而在Object类的默认实现中,equals()方法的底层是通过==来实现的。

StringBuilder和StringBuffer的区别

1.**在线程安全上 :
—StringBuffer是旧版本就提供的,线程安全的。@since JDK1.0
—StringBuilder是jdk1.5后产生,线程不安全的。@since 1.5
2. 在执行效率上,StringBuilder > StringBuffer > String
3.**源码体现:本质上都是在调用父类抽象类AbstractStringBuilder来干活,只不过Buffer把代码加了同步关键字,使得程序可以保证线程安全问题。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
**

DAY12

BigDecimal/BigInteger

概述:
BigDecimal:常用来解决精确的浮点数运算
BigInteger: 常用来解决超大的整数运算

创建对象

BigDecimal(double val)
**double转换为BigDecimal,后者是double的二进制浮点值十进制表示形式,有坑**!
BigDecimal(String val)
****String类型字符串的形式转换为BigDecimal

常用方法

Add(BigDecimal bd) : 做加法运算
Subtract(BigDecimal bd) : **做减法运算
Multiply(BigDecimal bd) : **做乘法运算
Divide(BigDecimal bd) : **做除法运算,除不尽时会抛异常
Divide(BigDecimal bd,保留位数,舍入方式) : 除不尽时使用
setScale(
保留位数,舍入方式**) : 同上
pow(int n) : 求数据的几次幂

练习1:测试常用方法

  1. /**本类用于测试浮点数运算时不精确的解决方案--BigDecimal*/
  2. public class Test1_BigDecimal {
  3. public static void main(String[] args) {
  4. //method();//使用 + - * / 完成运算,暴露浮点数运算不精确的问题
  5. method2();//使用BigDecimal来解决浮点数运算不精确的现象
  6. }
  7. public static void method2() {//20:45接着继续,大家抓紧时间完成,一会我们进IO啦
  8. //1.提示并接收用户输入的两个小数
  9. System.out.println("请输入您要计算的两个小数:");
  10. double a = new Scanner(System.in).nextDouble();
  11. double b = new Scanner(System.in).nextDouble();
  12. //2.创建工具类对象,把基本类型的a和b交给工具类对象BigDecimal来保存
  13. /**1.最好不要使用double作为构造函数的参数,不然还会产生不精确的现象,有坑!!!!*/
  14. /**2.最好使用重载的,参数类型是String的构造函数,double转String,直接拼个空串就可以*/
  15. BigDecimal bd1 = new BigDecimal(a+"");
  16. BigDecimal bd2 = new BigDecimal(b+"");
  17. //3.通过BigDecimal上的方法,做精确运算
  18. //3.1定义对象来保存结果
  19. BigDecimal bd3;
  20. //3.2 add(BigDecimal bd) : 做加法运算
  21. bd3 = bd1.add(bd2);
  22. System.out.println(bd3);
  23. //3.3 subtract(BigDecimal bd) : 做减法运算
  24. bd3 = bd1.subtract(bd2);
  25. System.out.println(bd3);
  26. //3.4 multiply(BigDecimal bd) : 做乘法运算
  27. bd3 = bd1.multiply(bd2);
  28. System.out.println(bd3);
  29. //3.5 add(BigDecimal bd) : 做除法运算
  30. /**java.lang.ArithmeticException,除法运算,除不尽时会抛异常*/
  31. //bd3 = bd1.divide(bd2);--方案一
  32. /**divide(m,n,o) --m是要除以哪个对象保存的值,n要保留几位,o是摄入方式,最常使用的是四舍五入*/
  33. bd3 = bd1.divide(bd2, 3, BigDecimal.ROUND_HALF_UP);//方案二:
  34. System.out.println(bd3);
  35. }
  36. public static void method() {
  37. //1.提示并接收用户输入的两个小数
  38. System.out.println("请输入您要计算的两个小数:");
  39. double a = new Scanner(System.in).nextDouble();
  40. double b = new Scanner(System.in).nextDouble();
  41. //2.做运算
  42. System.out.println( a + b );//不精确
  43. System.out.println( a - b );//不精确
  44. System.out.println( a * b );//不精确
  45. System.out.println( a / b );//不精确
  46. }
  47. }

IO简介

继承结构

In/out 相对于程序而言的输入(读取)/输出(写出)的过程.
在java中,根据处理的数据单位不同,分为字节流和字符流
字节流 : 针对二进制文件
字符流 : 针对文本文件,读写容易出现乱码的现象,在读写时,最好指定编码集为UTF-8

Java.io包下:
File
字节流:
InputStream
—FileInputStream
—BufferedInputStream
—ObjectInputStream
OutputStream
—FileOutputStream
—BufferedOutputStream
—ObjectOutputStream
字符流:
Reader
—FileReader
—BufferedReader
—InputStreamReader
Writer
—FileWriter
—BufferedWriter
—OutputStreamWriter
—PrintWriter一行行写出

Stream流的概念

数据的读写可以抽象成数据在管道中流动
流只能单方向流动
输入流用来读取à in
输出流用来写出 àout
数据只能从头到尾顺序的读写一次

File文件流

创建对象

File(String pathname)通过将给定路径名字符串转换为抽象路径名来创建一个新的File实例
new File(“d:/abc/a.txt”);
new File(“d:/abc”,”a.txt”);

练习**2**:测试常用方法

  1. /**本类用于测试文件流*/
  2. public class Test2_File {
  3. public static void main(String[] args) throws IOException {
  4. //1.创建File对象
  5. //参数是具体的路径,可以是文件的路径,也可以是文件夹的路径
  6. //注意:需要手动在windows中创建D:\ready\1.txt并添加内容
  7. /**1.\在代码中具有特殊的意义,转义的作用,
  8. * 所以表示这个是一个真正的斜杠,需要转义一下*/
  9. File file = new File("D:\\ready\\1.txt");//创建的是java对象
  10. //2.测试常用方法
  11. //2.1文件与文件夹属性
  12. System.out.println(file.length());//15,获取指定文件的字节量
  13. System.out.println(file.exists());//true,判断指定文件是否存在
  14. System.out.println(file.isFile());//true,判断指定内容是否是文件
  15. System.out.println(file.isDirectory());//false,判断指定内容是否是文件夹
  16. System.out.println(file.getName());//1.txt,获取文件名
  17. System.out.println(file.getParent());//D:\ready,获取父级目录
  18. System.out.println(file.getAbsolutePath());//D:\ready\1.txt,获取绝对路径
  19. //2.2创建与删除
  20. file = new File("D:\\\\ready\\\\2.txt");
  21. /**如果指定创建文件的文件夹不存在
  22. * 会抛出异常:java.io.IOException:系统找不到指定的路径
  23. * 所以需要处理,目前的方式是抛出异常*/
  24. System.out.println(file.createNewFile());//在win中创建不存在的文件2.txt
  25. file = new File("D:\\ready\\m");
  26. System.out.println(file.mkdir());//在win中创建不存在的单级目录
  27. file = new File("D:\\ready\\a\\b\\c");
  28. System.out.println(file.mkdirs());//在win中创建不存在的多级目录
  29. System.out.println(file.delete());//删除文件或者空文件夹,c文件夹被删除
  30. file = new File("D:\\ready\\a");
  31. System.out.println(file.delete());//由于a目录里还有b目录,所以删除不了
  32. //2.3文件列表
  33. file = new File("D:\\ready");
  34. //查看文件夹下所有文件的名称,返回值类型是String[]
  35. String[] list = file.list();
  36. System.out.println(Arrays.toString(list));
  37. /**列出文件夹中所有的文件夹和文件对象,返回值是File[]
  38. * 数组的每个元素都是File对象,可进一步操作
  39. * */
  40. File[] listFiles = file.listFiles();
  41. System.out.println(Arrays.toString(listFiles));
  42. System.out.println(listFiles[0].length());
  43. }
  44. }

练习**3**:递归求目录总大小
需求:递归求目录的总大小 D:\ready,步骤分析如下:
1.列出文件夹中的所有资源—listFiles()—>File[]
2.判断,当前资源是文件还是文件夹—文件夹大小为0,文件大小需要累加
—是文件,求文件的字节量大小length(),累加就行
—是文件夹,继续列出文件夹下的所有资源—listFiles()—>File[]
—判断,是文件,求文件的字节量大小length(),累加就行
—判断,是文件夹,再一次列出文件夹下的所有资源
—……重复操作
也就是说,规律就是:只要是文件夹,就需要重复步骤1 2

  1. /**本类用来递归求目录总大小*/
  2. public class Test3_FileSumRecursion {
  3. public static void main(String[] args) {
  4. //1.指定要求哪个目录的总大小
  5. /**注意:此处指定的目录必须是真实存在的
  6. * 如果传一个不存在的文件夹会报错,如果是传了一个空文件夹,大小为0*/
  7. File file = new File("D:\\ready");
  8. //2.调用size()求目录大小
  9. long total = size(file);
  10. //3.接收结果并打印
  11. System.out.println("文件夹的总大小为:"+total);
  12. }
  13. private static long size(File file) {
  14. //1.列出文件夹中的所有资源--listFiles()-->File[]
  15. File[] fs = file.listFiles();
  16. //2.遍历数组,获取每file对象
  17. //2.1定义变量,记录总和
  18. long sum = 0;
  19. for(int i = 0;i < fs.length ; i++) {
  20. //2.2通过下标操作当前遍历到的资源
  21. File f = fs[i];
  22. //2.3判断,当前资源是文件还是文件夹--文件夹大小为0,文件大小需要累加
  23. if(f.isFile()) {
  24. //--是文件,求文件的字节量大小length(),累加就行
  25. sum += f.length();//相当于:sum = sum + f.length();
  26. }else if(f.isDirectory()) {
  27. //--是文件夹,继续列出文件夹下的所有资源,1 2步骤--listFiles()-->File[]
  28. /**方法的递归,递归现象,就是在方法的内部调用方法自身*/
  29. sum += size(f);
  30. }
  31. }
  32. return sum;//把sum记录的值返回调用位置
  33. }
  34. }

字节流读取

InputStream抽象类
此抽象类是表示字节输入流的所有类的超类/抽象类,不可创建对象哦

FileInputStream子类

直接插在文件上,直接读取文件数据
创建对象
FileInputStream(File file)—直接传文件对象
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定FileInputStream(String pathname)—传路径
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定

BufferedInputStream子类

BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组(默认8k大小)。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。
创建对象
BufferedInputStream(InputStream in)创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

练习**5**:字节流读取案例

  1. /**本类用于测试文件的读取*/
  2. public class Test4_In {
  3. public static void main(String[] args) {
  4. method();//字节流的读取
  5. method2();//高效字节流的读取
  6. }
  7. public static void method() {
  8. InputStream in = null;
  9. try {
  10. //1.创建字节流读取对象
  11. //new InputStream();//报错:抽象父类不可以创建对象
  12. //FIS传入的参数是一个File对象
  13. //InputStream in2 = new FileInputStream(new File("D:\\ready\\4.txt"));
  14. //FIS传入的参数是一个路径,保证此路径下的文件是存在且有内容的
  15. in = new FileInputStream("D:\\ready\\4.txt");
  16. //2.开始读取,read()每次读取1个字节,如果读到了数据的末尾,返回-1
  17. // System.out.println(in.read());//97
  18. // System.out.println(in.read());//98
  19. // System.out.println(in.read());//99
  20. // System.out.println(in.read());//-1
  21. //3.1定义变量,记录读到的数据
  22. int b;
  23. while((b = in.read()) != -1) {//3.2返回值为-1的时候表示没有数据了,循环结束
  24. //3.3打印每次读取到的内容
  25. System.out.println(b);
  26. }
  27. } catch (IOException e) {
  28. e.printStackTrace();//打印错误信息到控制台
  29. } finally {//try-catch-finally,finally中的代码一定会被执行,常用于关流
  30. try {
  31. //4.释放资源
  32. in.close();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }
  38. public static void method2() {
  39. BufferedInputStream in = null;
  40. try {
  41. //1.创建高效字节流读取对象
  42. //new InputStream();//报错:抽象父类不可以创建对象
  43. //BIS是高效的读取流
  44. // in2 = new BufferedInputStream(
  45. // new FileInputStream(new File("D:\\ready\\4.txt")));
  46. in = new BufferedInputStream(
  47. new FileInputStream("D:\\ready\\4.txt"));
  48. //2.开始读取,read()每次读取1个字节,如果读到了数据的末尾,返回-1
  49. // System.out.println(in.read());//97
  50. // System.out.println(in.read());//98
  51. // System.out.println(in.read());//99
  52. // System.out.println(in.read());//-1
  53. //3.1定义变量,记录读到的数据
  54. int b;
  55. while((b = in.read()) != -1) {//3.2返回值为-1的时候表示没有数据了,循环结束
  56. //3.3打印每次读取到的内容
  57. System.out.println(b);
  58. }
  59. } catch (IOException e) {
  60. e.printStackTrace();//打印错误信息到控制台
  61. } finally {//try-catch-finally,finally中的代码一定会被执行,常用于关流
  62. try {
  63. //4.释放资源
  64. in.close();
  65. } catch (IOException e) {
  66. e.printStackTrace();
  67. }
  68. }
  69. }
  70. }