第三周学习总结

一、内部类(inner class)

1、定义

在一个类中,定义另一个类的代码结构,通常定义在类内部的类称为 “内部类” ,外面的类称为“外部类” , 在逻辑关系上 内部类与外部类是从属关系,比如 一个People类 存在收货地址类(收货人,收货联系方式)

2、分类

2.1、 普通内部类(inner class),一个类A中定义另一个类B,其中类B就是类A的内部类,也是类A的一部分

注意两点

  • 外部类的方法中,可以直接访问内部类的所有成员(包括私有)

  • 内部类的方法中,也可以直接方法外部类的所有成员,当外部和内部的成员名相同时,就近原则访问成员,或者引入外部类的对象访问

2.2、 静态内部类(static inner class): 在普通内部类基础上,增加“static”关键字,与静态方法相似,满足静态的要求

2.3、方法内部类: 在一个方法中定义的类,其中这个类只属于该方法,也只能在该方法中使用

2.4 匿名内部类: 定义一个没有类名,只有对方法的具体实现。通常它依赖于实现关系(接口)或继承关系(父类)

a、基于实现关系

public interface MyInterface {
    // 学习
    public void  study();
    //  工作
    public void work();
}
// 创建一个匿名类(让接口的引用 指向匿名类的对象)
        MyInterface  person = new MyInterface() {
            @Override
            public void study() {
                System.out.println("这个人也好好学习");
            }

            @Override
            public void work() {
                System.out.println("这个人也好好工作");
            }
        };

        person.study();
        person.work();

b、基于继承关系

public class MyClass {

   public void service(){
        System.out.println("提供服务的方法。");
    }
}
 // 父类 new 一个 匿名类,这个匿名类是它的子类
        MyClass cls = new MyClass(){
            @Override //匿名类重写父类的方法 service
            public void service() {
                System.out.println("这是子类的方法");
            }
        };
        cls.service();

 

二、异常

1、异常的概述

异常定义: 在程序中,发生“不正常”的事件,导致程序无法正常运行,并使JVM中断,称为异常

生活中的异常: 早上起床上课,平时骑车20分钟可以到达教室,由于天气原因或者闹钟响了自动关闭,不能按时到达教室上课,迟到了,此时就属于异常现象 。

捕获异常: 当程序在运行时,发生了异常 ,为了让程序正常执行,需要对异常捕获(catch),称之为捕获异常

Java是面向对象的语言, 异常本身就是一个类(Exception),当发生异常时会创建异常对象,捕获的就是该对象。

 

2、异常关键字 以及层次关系

a、try: 试一试 ,将可能发生的代码使用try包裹 ,try不能单独出现

b、catch : 捕获异常, 当发生指定的异常对象时,执行catch代码

System.out.println("请输入一个数字");
        Scanner sc = new Scanner(System.in);
        // 对可能发生的异常 进行处理
        try {
            int num = sc.nextInt();  // 发生异常后,try里面的代码不再执行
            if (num % 2 == 0) {
                System.out.println("这个数是偶数");
            }
            System.out.println("结束");
        }catch(Exception ee){// 对应的异常类 来捕获对应的异常对象  ,不能确定异常类,可以使用父类Exception
            System.out.println("你的输入不正确");
        }

        System.out.println("程序继续运行直到结束。。。。");

一个try + 多个catch

//  抛出的异常 不能被catch捕获,会发生什么?
        try {
            int[] num = {1, 2, 3};
            System.out.println(num[1]); // 没有捕获该异常对象,JVM依然终止运行
            System.out.println(10/0);
        }catch(NullPointerException ee){
            System.out.println("这是空指针异常");
        }catch(ArrayIndexOutOfBoundsException  ee){
            System.out.println("数组下标越界异常");
        }catch(Exception ee){
            // 输出异常 堆栈消息  方便程序员排错(尽可能避免用户看见)
            ee.printStackTrace();
            System.out.println("系统繁忙!"+ee.getMessage());
        }
        System.out.println("程序结束");

c: finally : 异常之后的最终处理 (无法是否发生异常,程序都执行 )

try... finally 结构

	 try{
            System.out.println("请输入两个数 ,计算两个数相除");
            Scanner sc = new Scanner(System.in);
            int  num1 =  sc.nextInt();
            int num2 = sc.nextInt();
            double  s = num1/num2; // 可能出错
            System.out.println(" try里面结束,结果:"+s);
        }finally{
            System.out.println("无论是否发生异常,都会执行这个语句块,一般用于资源回收");
        }

try... catch...finally 结构

try {
            System.out.println("请输入两个数 ,计算两个数相除");
            Scanner sc = new Scanner(System.in);
            int num1 = sc.nextInt();
            int num2 = sc.nextInt();
            double s = num1 / num2; // 可能出错
            System.out.println(" try里面结束,结果:" + s);
        }catch(ArithmeticException ee){
            ee.printStackTrace();
            System.out.println("除数不能为0 !!");
        }catch(Exception ee){
            ee.printStackTrace();
            System.out.println("系统繁忙!!!");
        }finally {
            System.out.println("用于资源回收。");
        }

3、异常分类

由于有些异常是不能直接抛出的 ,需要先声明才可以抛出,异常可以分为两大类:

1、 编译期异常(check 异常或者检查异常):在编译期间检查异常,如果没有处理异常,则编译出错。

//创建一个文件类的对象
        File  file = new File("d:/aaa.txt");
         // 在写代码(编译之前)时 一定要处理的异常(try..catch 或者 throws),就是编译时异常 
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

这里的IOException 就是 编译期异常,需要手动处理的

2、运行期异常(runtime 异常或者运行异常):在运行期间检查异常, 编译期可以不处理异常。

        // 在运行期间抛出异常  不需要事先处理的  NullPointException是运行异常
        String str=null;
        System.out.println(str.length());

Exception中常用的异常类

  • RuntimeException

    • ArrayIndexOutOfBoundsException :数组下标越界异常

    • NullPointerException:空指针异常

    • ArithmeticException: 算术异常

    • NumberFormatException :数字格式化异常

    • ClassNotFoundException: 类没找到异常

    • ClassCaseException: 类转换异常

  • 检查异常(check Exception)

IOException :IO操作

FileNotFoundException: 文件未找到异常

SQLException:

EOFException:读写文件尾异常

DateFormatException:日期格式化异常

SocketException:SocketException

注意: 对于抛出检查异常,需要使用throws声明,对于抛出运行时异常,必须要使用throws声明

 

面试题: 关于 finally 和 return的执行顺序问题?

回答: 当方法有返回值时,先执行fianlly,再return, 但是 finally的代码不会改变return结果

 

4、自定义异常

1、为什么需要使用自定义异常

在Java中每一个异常类都表示特定的异常类型, 例如 NullPointerException表示空指针 ,ArithmeticException表示算术异常, 但是sun公司提供的API中不可能将实际项目中的业务问题全部定义为已知的异常类 ,这是需要程序员根据业务需求来定制异常类,例如 用户注册,可以定义用户注册异常(RegisterException),分数不能为负数也可以定制异常(ScoreExcecption)。

2、什么是自定义异常

在开发中根据自己的业务情况来定义异常类 , 灵活性较高,且方便易用。

3、如何实现自定义异常

a、定义编译期异常类,创建一个类继承 java.lang.Exception ;

b、定义运行期异常类,创建一个类继承java.lang.RuntimeException;

 

三、包的结构与功能介绍

Java是一门面向对象的语言,sun公司提供基于面向对象的帮助文档(API Application Program Interface) ,并针对不同的版本生成的API

API中根据不同的功能分如下包 (package)

  • java.applet.* : java的小应用程序

  • java.awt.* 和 java.swing.* : java的图形用户界面(开发单机版的小游戏)

  • java.lang.* : java的语言包

  • java.util.* : java的工具类包、集合框架包

  • java.io.* : java文件读写包(Input 、Output)

  • java.net.* : java的网络编程包(Socket机制相关,URL)

  • java.sql./ javax.sql. : java的数据库操作

  • java.lang.reflect.* 反射相关包

四、java的lang包

1、包装类

定义: Java的8个基本数据类型对应的 对象类型,称为它们的包装类

为什么需要包装类:

基本数据类型中不能提供方法, 不能与其他引用数据类型转换,此时包装类作为该基本数据类型的对象类型,不仅提供常用的方法,还可以与其他数据类型互相转换 和 “装箱”、“拆箱”

问题1: 基本数据类型、包装类以及字符串的相互转换

public static void main(String[] args) {
        // 1、byte 的包装类   Byte
        // 创建包装类的对象
        byte b=123;
        Byte obj1 = new Byte(b);
        //1、 包装类 转字符串   包装类对象.toString()
        String s1 = obj1.toString();

        //2、字符串转包装类      new 包装类(s) 或者   包装类.valueOf(s)
        String s2="100";
        Byte obj2 = new Byte(s2);
        // 或者
        Byte obj3 = Byte.valueOf(s2);



        //3  获取包装类的数值,包装类转基本数据类型  Byte  - >  byte
        //  包装类.valueOf(基本数据类型) 或者 byteValue()
        byte b2 = obj2;  // 包装类可以直接复制给基本数据类型  ,这个过程 “拆箱”过程
        byte b3 = Byte.valueOf(obj2);

        // 4、字符串转 基本类型     包装类.paseByte(s)
        byte b4 = Byte.parseByte(s2);


        byte b5=122;
        String s5 = new Byte(b5).toString();


    }

问题2: 数据类型的装箱和拆箱

装箱: 将基本数据类型自动转换成 它的包装类,可以使用包装类的方法和属性

 // 自动装箱: 100自动转成 Integer 
        Integer num1 = 100;

拆箱: 将包装类型 自动转成 对应的基本数据类型。

// 自动拆箱:  Integer 自动转成  int
        int num2 = num1;

面试题:

public static void main(String[] args) {
        // 包装类
        // 自动装箱: 100自动转成 Integer
        Integer num1 = 100;
        // 自动拆箱:  Integer 自动转成  int
        int num2 = num1;

        Integer n1 =100;
        Integer n2 =100;
        System.out.println(n1.equals(n2)); //true
        System.out.println(n1 == n2);// 应该true   他们同时指向常量池100


        Integer n3 = 150; // 等价于 Integer n3 = new Integer(150);
        Integer n4 = 150; // 等价于 Integer n4 = new Integer(150);
        System.out.println(n3.equals(n4));//true
        System.out.println(n3 == n4);//false

        Integer n6 = new Integer(100);// 一定会创建新对象
        System.out.println(n6 == n1); // false

    }
        //结论
		//对于    -128 <=Integer的值 <=127 之间(byte范围),
        // 装箱时不会创建新对象 而是直接引用 常量池中的值
        // 如果超出byte 的返回,则自动创建新对象,各自指向新对象的内存

2、Object类

Object类是lang包提供的 ,对于lang包的类不需要import,所以 Object类无处不在,你不需要自己创建

常用方法

a、getClass: 返回该对象的类型 任何类都有它的类型

b、equals : Java中所有的equals 方式都是重写Object的方法

原生的equals 比较的是 对象的地址 ,我们通常说的 equals比较两个对象的值是因为几乎所有的数据类型(包装类,String)都重写了equals 方法的

 public boolean equals(Object obj) {
        return (this == obj);
    }

c、 hashCode() : 返回该都对象的hash值

d:finalize() 资源回收调用该方法, 当对象地址不在被引用时,会被GC回收 并调用该方法

Object obj = null ;

c:toString() : 返回该对象的字符串表现形式 (通常会被子类重写)

wait():线程等待

notify():唤醒其中一个等待的线程

notifyAll:唤醒所有等待中的线程

 

对象的比较

public static void main(String[] args) {
          // 创建对象   比较对象是否相等
        // 比较内存相等 或 比较值(对象的属性)相等
        Student stu1 = new Student(1001,"敖园",22);
        Student stu2 = new Student(1001,"敖园",22);
        System.out.println(stu1==stu2);  // 比较两个对象的地址 (不相等)    false
        System.out.println(stu1.equals(stu2));   // true
        // 由于equals本身没办法解决
        //    两个对象因id 和name相等业务上是同一个对象的问题
        // 所以需要重写 equals 和 hashcode 。
         // 为什么要重写HashCode呢?
        //  回答: 在JMV中如果HashCode不相等,一定不能认为是同一个对象

        Student stu3 = stu1;  // stu3 的地址于stu1的地址是同一个

    }

总结: 对象之间的比较 ,通常是比较属性值,如果属性值相等,我们可以认为是同一个对象,

此时需要重写 equals 和hashcode方法。

为什么要重写HashCode呢?

回答: 在JMV中如果HashCode不相等,一定不能认为是同一个对象

3、System类

public static void main(String[] args) {
        // System 属于系统类
       //  System.out; // 获取控制台的打印流
        // 设置JVM运行时 系统参数
        System.setProperty("encoding","UTF-8");
        System.out.println("获取:"+System.getProperty("encoding"));
        // 时间从 1970-01-01
        System.out.println("获取当前系统的时间毫秒数:"+ System.currentTimeMillis());

        System.exit(0); // 0 : 表示JVM正常退出    -1 表示非正常退出

    }

 

4、字符串类

java.lang.String类,Java中所有的字符串都会创建该类的实例 , 它可以对字符串查找,检索,转变大小写,截取等一系列操作,并提供了大量的字符串操作方法。

String类的特点:

它是一个不可变字符串 ,它的值创建后不能被改变。

String的构造器

// 创建字符串对象
        String s1="abc";
        String s2 = new String("abc");
        //通过字符数组构建
        char [] chars = {'a','b','c'};
        String s3 = new String(chars);  //  或指定长度构建字符串
        String s4 = new String(chars,0,2);
        //或根据字节数组构建
        byte [] byts = {97,98,99};
        String s5 = new String(byts);

        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);
        System.out.println(s5);
// 字符串是一个不可变的对象
        // class类被JVM装载时,会分配一个存放字符串的常量池(String Pool)
        // 在类加载时 先检查常量池中是否有“abc”常量,如果有,直接将ss1指向该常量
        // 如果没有,则创建常量abc
        // 创建2个对象
        String ss1 = "abc";
        //  abc常量不能改变,  则再创建 abcd的常量,由ss1重新指向
        ss1+="d";
        // 创建3个对象
        String ss2 ="abcd";  // abcd
        String ss3 = "aaa";  // aaa
        ss2 += ss3;  // abcdaaa   重新创建abcdaaa并由ss2重新指向
String a1="abc";
        String b1="abc"; // 两个地址同时指向一个常量 “abc”
        System.out.println(a1==b1);  // true
        System.out.println(a1.equals(b1));

        String c1=new String("abc");// 堆内存中  对abc包装后的地址
        System.out.println(a1==c1);  // false
        System.out.println(a1.equals(c1));//true

字符串类常用方法

  • 将此字符串与指定对象进行比较:public boolean equals (Object anObject)

  • 将此字符串与指定对象进行比较,忽略大小写:public boolean equalsIgnoreCase (String anotherString)

举例:

public static void main(String[] args) {
		String s1 = "hello";
		String s2 = "hello";
		String s3 = "HELLO";
		
		//boolean equese(Object obj):比较字符串的内容是否相同
		System.out.println(s1.equals(s2));
		System.out.println(s1.equals(s3));
		System.out.println("-------------");
		
		//boolean equalsIgnoreCose(String str):比较字符串的内容是否相同,忽略大小写
		System.out.println(s1.equalsIgnoreCase(s2));
		System.out.println(s1.equalsIgnoreCase(s3));
		System.out.println("--------------");
	}

4.1、获取功能的方法

  • 返回字符串的长度:public int length()

  • 将指定的字符串连接到该字符串的末尾:public String concat (String str)

  • 返回指定索引处的char值:public char charAt (int index)

  • 返回指定字符串第一次出现在该字符串内的索引:public int indexOf(String str)

  • 返回一个子字符串,从beginIndex开始截取字符串到字符串结尾:public String substring (int beginIndex)

  • 返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndexpublic String substring (int beginIndex,int endIndex)

举例:

public static void main(String[] args) {
		
		String s = "helloworld";
		//length() :获取字符串的长度,其实也就是字符的个数
		System.out.println(s.length());
		System.out.println("---------");
		
		//String concat (String str):将指定的字符串连接到该字符串的末尾
        String s2 = s.concat("**hellow itheima");
        System.out.println(s2);
        
        //charAt(int index):获取指定索引处的字符串
        System.out.println(s.charAt(0));
        System.out.println(s.charAt(1));
        System.out.println("-------");
        
        //int indexOf(String str):获取str在字符串对象中第一次出现的索引,没有返回-1
        System.out.println(s.indexOf("l"));
        System.out.println(s.indexOf("owo"));
        System.out.println(s.indexOf("ak"));
        System.out.println("---------");
        
        //String sbustring(int start):截取从start开始,到字符串结尾的字符串
        System.out.println(s.substring(0));
        System.out.println(s.substring(5));
        System.out.println("----------");
        
        //String substring(int start,int end):从start到end截取字符串,含start,不含end
        System.out.println(s.substring(0,s.length()));
        System.out.println(s.substring(3,8));

	}

4.2、转换功能的方法

  • 将字符串转换为新的字符数组:public char[] toCharArray()

  • 使用平台的默认字符集将该String编码转换为新的字节数组:public byte[] getBytes()

  • 将与targer匹配的字符串使用replacement字符串替换public String rep;ace (CharSequence targer,CharSequence replacement)

举例:

public static void main(String[] args) {
		
		String s = "helloworld";
        
        //char[] toCharArray():把字符串转换为字符数组
        char[] chs = s.toCharArray();
        for(int x = 0 ; x < chs.length;x++){
        	System.out.println(chs[x]);
        }
        System.out.println("---------");
        
        //byte[] getBytes():把字符串转换为字节数组
        byte[] bytes = s.getBytes();
        for(int x = 0;x < bytes.length; x++){
        	System.out.println(bytes[x]);
        }
        System.out.println("--------");
        
        String str = "softeem";
        String replace = str.replace("s","S");
        System.out.println(replace);

4.3、分割功能的方法

将字符串按照给定的regex(规则)拆分为字符串数组:public String[] split(String regex)

举例:

public static void main(String[] args) {
		String s = "aa|bb|cc";
		String[] strArray = s.split("|");
		for(int x = 0;x < strArray.length; x++){
			System.out.println(strArray[x]);
		}
	}

五、StringBuffer和StringBuilder类

1、StringBuffer 类

是一个字符串缓冲区的类,线程安全运行效率低,用户存储可变字符串

构造器:

 StringBuffer  sb = new StringBuffer(); // 创建空字符串的容器
  StringBuffer sb = new StringBuffer(String);// 将字符串使用容器存储
  StringBuffer sb = new StringBuufer(int);//声明指定容量的容器

常用方法:

1.1、append():追加字符串

1.2、delete(int start,int end):删除指定位置的字符

1.3、insert(int start ,String):插入到指定位置

1.4、reverse():反转字符

1.5、capacity():获取初始容量

1.6、ensureCapacity(int):设置最低所需容量

2、StringBuilder类

也是字符串缓冲区的类,它是线程不安全,且运行效率高的可变字符串缓冲类

其StringBuilder的方法与StringBuffer几乎一样

3、面试题

1、StringBuffer、StringBuilder和String的区别

a、在运行速度上 : StringBuilder > StringBuffer > String

原因: String是字符串常量,而StringBuilder和StringBuffer是字符串变量,当需要改变字符串内容时,Stirng重新创建变量并赋值, 而StringBuilder和StringBuffer可直接改原有的值,所有效率高,

b、在线程安全上: StringBuffer > StringBuilder > String

原因: StringBuffer是线程安全的,而StringBuilder线程不安全,在StringBuffer上的很多方法增加同步关键字(synchronized),导致在多个线程运行时,保持数据的完整性和一致性,而StringBuilder的方法并没有同步 ,如果在多线程环境下为了确保数据安全,建议使用StringBuffer ,如果在单线程环境下,提高效率使用StringBuilder。

 

六、Math类

java.lang.Math类用于数学计算的工具类 ,它提供都是静态方法 ,不需要构造Math对象

常用方法:

Math.random():获取随机数

Math.abs() 获取绝对值

Math.ceil(): 向上取整

Math.floor() :向下取整

Math.rint():取接近它的整数 ,如果两个同样接近,往偶数靠近

Math.max(int,int):返回两个数的最大值

Math.min(int,int):返回两个数的最小值

Math.round():四舍五入整数

Math .sqrt():对一个数开平方

Math.pow(double,double),对一个数的几次幂

 public static void main(String[] args) {
        System.out.println(Math.PI);
        System.out.println(Math.E);
        System.out.println(" 一个数的绝对值:"+Math.abs(-100));//100
        System.out.println(" 向上取整:"+Math.ceil(13.5)); // 14
        System.out.println(" 向上取整(比它大的最近数):"+Math.ceil(-13.5));// -13
        System.out.println("向下取整:"+ Math.floor(13.5));// 13
        System.out.println("向下取整"+Math.floor(-20.2));// -21

        //四舍五入
        System.out.println(Math.round(23.4));// 23
        System.out.println(Math.round(-23.5));//-23
        System.out.println(Math.round(-24.5));//-24

        System.out.println(Math.rint(23.4));// 23
        System.out.println(Math.rint(23.5));//24 如果两个一样接近,取接近偶数
        System.out.println(Math.rint(22.5));//22
        System.out.println(Math.rint(0.6));//0

    }

七、大数据类型BigDecimal

1、BigDecimal类

两个double类型的计算可能导致精度不准确,这里使用

java.math.*里面提供了BigDecimal类(提供高精度计算的方法)

public static void main(String[] args) {
         double a= 1.200000;
         double b= 1.35433;
         double c = a+b;
        System.out.println(c);
        System.out.println(0.05+0.01);
        System.out.println(1.0-0.42);  // 会出现精度问题  计算不准确

        // 使用BigDecimal ,先将类型转成字符串 (为了避免精度问题)
        BigDecimal num1 = new BigDecimal("0.051");
        BigDecimal num2 = new BigDecimal("0.012");
        // 两个数相加

        BigDecimal sum = num1.add(num2 ) ;
        // 设置保留2位整数  四舍五入
        sum =sum.setScale(2,BigDecimal.ROUND_HALF_UP);
        System.out.println(sum);

        // 减法
       sum =  num1.subtract(num2);
        System.out.println(sum);

       // 乘法
       sum =  num1.multiply(num2);
        System.out.println(sum);

       // 除法
       sum = num1.divide(num2,2,BigDecimal.ROUND_HALF_UP);
        System.out.println(sum);

    }

2、NumberFormat类

java.text.NumberFormat类 :用于将数值格式转成指定格式并输出字符串形式的类 。

DecimalFormat类: 属于NumberFormat的子类。

 // NumberFormat类是对数值类型的格式化类,其中 DecimalFormat是继承NumberFormat
        // 获取数值的货币表现形式
        NumberFormat nf = NumberFormat.getCurrencyInstance();
        String s1 = nf.format(23424.2);
        System.out.println(s1);

        //获取数值的百分比
        nf = NumberFormat.getPercentInstance();
        s1= nf.format(0.654);
        System.out.println(s1);

        //根据指定的格式匹配百分比
        nf = new DecimalFormat("##.##%");
        s1=nf.format(0.654);
        System.out.println(s1);

        // 根据指定的模式匹配千分比
        nf = new DecimalFormat("##.##\u2030");
        s1 = nf.format(0.6543);
        System.out.println(s1);

        // 根据指定的模式 转成科学计数法
        nf = new DecimalFormat("#.###E0");
        s1 = nf.format(198200);
        System.out.println(s1);

        // 根据指定的模式  将字符串转成 指定格式数值型
        String s2 ="25.3%";
        nf = new DecimalFormat("##.##%");
        Number dd = nf.parse(s2);
        double num = (double)dd;
        System.out.println("这个字符串转成double:"+num);

 

八、日期和日历类

1、日期类 Date

在Java中用于表示日期的类 java.util.Date() ,用于获取日期和时间的对象, 不过这个类的一些方法以及过时(被日历类取代)

创建日期类

  // 创建日期类的对象
        Date date = new Date();
        //获取当前时间 以 标准格式
        System.out.println(date);
        // 获取当前时间的毫秒数
        System.out.println(date.getTime());
        //通过毫秒数构建当前时区的 时间
        Date date2 = new Date(100000);
        System.out.println(date2);

        // 获取 纪元时间  相隔本地时间8时区
        System.out.println(date.toGMTString());
        System.out.println(date.toLocaleString());

        //测试时间的先后
        System.out.println(date.after(date2));// true
        System.out.println(date.before(date2));//false
        System.out.println(date.compareTo(date2));//比较时间大小
        // 时间转成字符串
        System.out.println(date.toString());

2、日历类 Calendar

java.util.Calendar 是表示日历类, 它是一个单例模式 ,通过 getInstance()获取一个日历对象, 并获取日历的任意时间,日期。

常用方法

getInstance() : 获取日历对象

get() :获取指定的单位的日历数值 (年,月,日 等等)

set():设置指定单位的日历数值

add() :添加指定单位的日历数值

getTimeInMills() :获取日期的毫秒数

 // 获取当前日历对象
        Calendar cal =  Calendar.getInstance();
        // 日历的属性 (fields)
        System.out.println(Calendar.DATE);
        System.out.println(Calendar.YEAR);
        System.out.println(Calendar.MONTH);
        //获取当前日历的年份
        System.out.println(cal.get(Calendar.YEAR));
        // 获取月份 (返回 0-11)
        System.out.println(cal.get(Calendar.MONTH));
        // 获取日(1-31)
        System.out.println(cal.get(Calendar.DATE));
        // 获取日期
        System.out.println("获取当前日历的日期:"+ cal.getTime());
        // 添加日历 (指定的field 和 数量)
        // 将当前日历添加2个月
        cal.add(Calendar.MONTH ,2);
        System.out.println("新的日期:"+cal.getTime());
        cal.add(Calendar.DATE,-3);
        System.out.println("新的日期:"+cal.getTime());

        // 判断日期的前后 after  before
        // 题目 给定两个日期, 计算相差多少天
        Calendar cal1 = Calendar.getInstance();

计算两个日历(日期)的相差天数/月数

// 重写构建一个时间
        Calendar cal2 =  Calendar.getInstance();
        // 设置指定的时间
        cal2.set(2020,10,20);
        System.out.println("cal2---"+cal2.getTime());
        // 原始方式  通过毫秒数计算
        long  n =  cal1.getTimeInMillis()-cal2.getTimeInMillis();
        System.out.println("n---->"+n);
        long days =  n/(1000*60*60*24);
        System.out.println("days:"+days);

        // java8 的方式
        LocalDate date1 =   LocalDate.of(2020,2,22);
        LocalDate date2 =   LocalDate.of(2020,3,22);
        long days2 = date1.until(date2,ChronoUnit.DAYS);
        System.out.println("两个时间相差的天数:"+ days2);

3、字符串与日期格式的转换

 /**
     * 字符串转日期
     * @param str
     */
    public static Date strToDate(String str) throws ParseException {
        //使用格式化日期类    指定格式 :yyyy-MM-dd HH:mm:ss
        SimpleDateFormat  sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         // 指定格式的字符串 转成 日期
        return sdf.parse(str);

    }


/**
     * 日期转指定格式的字符串
     */
    public static String dateToString(Date date){
        // 使用同样的方式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        return sdf.format(date);
    }



// 调用转换方法
        String s = "2020-10-22 10:10:10";
        Date myDate= strToDate(s); // 注意 这里的格式需要匹配yyyy-MM-dd HH:mm:ss
        System.out.println(myDate);

        // 将日期转成字符串
        System.out.println(dateToString(myDate));

九、正则表达式

1、正则表达式定义

正则表达式(Regular Expression)由字母和符号组成的具有特定意义的公式,用于匹配或检索符合条件的字符串。

例如 在网页上输入用户名,要求用户名必须由数字,字母,下划线,或者长度必须8-16位之间 像这样的满足条件的公式,都是编写的 正则表达式进行验证。

^[a-zA-Z0-9_]{8,16}$

解释: ^ :表示以指定的字符开头

$:以指定符合结尾

[ a-zA-Z]: 字符必须是这个a-z或 A-Z之间的一个字符

{8,16}:匹配前面的字符8次到16次之间

正则表达式不属于某一门编程语言,可以在很多语言中使用, 例如 Java ,Python 、JS、MySql

Java提供对正则表达式的支持,有如下类

a、java.util.regex.Pattern 正则表达式的编译器类

b、java.util.regex.Matcher 正则表达式的匹配器

c、java.lang.String 中的方法自动兼容 正则语法

1、 元字符

元字符是组成正则表达式的最基本的符号 ,通常代表一定意义

元字符解释
.匹配任意一个字符
\w匹配一个数字,字母,_ 或汉字 \W :对\w取反
\d匹配一个数字 \D:对\d取反
\s匹配一个空白字符 \S:对\s取反
\b匹配以什么字符开头
^以指定的字符串开头 ,用于正则开始的标志位
$以指定的字符串结尾,用于正则结束的标志位

重复限定符

正则表达式中用于匹配重复次数的符号

 

重复限定符意义
*匹配前一个字符0次或多次
匹配前一个字符0次或1次
+匹配前一个字符1次或多次
{n}匹配前一个字符n次
{n,}匹配前一个字符至少n次
{n,m}匹配前一个字符n到m次(包含n次,m次)
 // 创建匹配格式的编译器
        String phone ="13388880000";
        Pattern pattern = Pattern.compile("1[356789][0-9]{9}");
        //  根据编译器获取匹配器
        Matcher matcher = pattern.matcher(phone);
        System.out.println("是否匹配目标字符串:"+matcher.matches());

        // 或者简写  匹配年龄 (0-100   01-09 | 10-99 |100)
       boolean flag =  Pattern.matches
               ("(0?[0-9])|([1-9][0-9])|(100)","10");

        System.out.println(flag);

        // 匹配一个特殊字符
        // 匹配一个字符串中是否包含 .
        String s2 ="adb";
        System.out.println(s2.matches(".*b.*"));
        // 因为.表示的所有字符  当匹配.时,需要转义
        System.out.println(s2.matches(".*\\..*"));

        // 对于特殊符号 需要转义   \\
        // 匹配邮箱   包含  任意字符任意个数@域名.com
        //    .cn  .com.cn  .gov  .net
        String email="1@softeem.com";
        System.out.println(email.matches("\\w+@\\w+(\\.[a-z]{2,3}){1,2}"));

        // 匹配一级网址 http://    https://d
        String url="http://www.baidu.com";
        System.out.println(url.matches("https?://www\\.\\w+\\.[a-z]{2,3}"));


        // 匹配生日格式   1900-13-01  ~ 2099-12-31   01  -31
        String birthday="1998-13-10"; // yyyy-MM-dd
        String regexp="((19)|(20))[0-9]{2}-((0[0-9])|(1[0-2]))-((0[1-9])|([1-2][0-9])|(3[0-1]))";
        System.out.println(birthday.matches(regexp));



// 匹配汉字
        String uname ="张";
        System.out.println(uname.matches("[\\u4E00-\\u9FFF]+"));

十、定时器类(Timer类)

1、Timer类

java.util.Timer类 是一个任务调度的定时器类,可以安排任务一次执行,或定期重复执行

创建Timer对象

Timer timer = new Timer();
 Timer timer = new Timer(name);

常用方法

timer.schedule(TimerTask,2000); 2秒后执行一次任务

timer.schedule(TimerTask,2000,1000); 2秒后开始执行任务,每1s执行一次

2、TimerTask类

java.util.TimerTask类是由定时器执行的任务类,是一个抽象类。

import java.util.Timer;
import java.util.TimerTask;

/**
 * ClassName: TestTimer
 * Description:
 * date: 2020/10/22 17:10
 *
 * @author wuyafeng
 * @version 1.0   softeem.com
 */
public class TestTimer {
    //统计打印次数
    static int count=0;
    // 创建一个定时器类
    static Timer timer = new Timer("我的定时器");

    public static void main(String[] args) {

        // 开始定时一个任务
        TestTimer obj = new TestTimer();
        // 多少毫秒之和 执行一次任务
      //  timer.schedule(obj.new MyTask(),2000);
        // 2秒之后开始执行,每隔1s执行一次
        timer.schedule(obj.new MyTask(),2000,1000);



    }
    // 定义内部类时,可以直接使用外部类的属性  和它的对象
    class MyTask extends TimerTask{

        @Override
        public void run() {
            System.out.println("你好!!!");
            count++;

            if(count>=10){
                System.out.println("停止");
                //停止
                timer.cancel();
            }
        }
    }
}

十一、泛型

1、泛型定义

泛型(generics)是JDK5.0以后的特性,提供了编译期间安全监测机制,它是将数据类型参数化的一种方式。 例如:在对方法进行编写参数列表时,以前我们需要知道方法的参数类型 ,现在使用泛型机制可以将方法的参数类型也作为 “未知的类型” ,在调用该方法时传递该类型。

2、泛型的使用

2.1 泛型类(generic class)

它是一种具有一个或多个类型变量的类,(一个变量可以有多种类型)

语法

 public  class  类<T>{
      // 类里面的数据类型 和 方法返回值,以及方法的参数都可以使用T  
      // <>里面可以是任意大写字母
      
  }
public class People<T> {
    private T name;
    private T sex;

    public T getName() {
        return name;
    }
       public People(T name,T sex){
        this.name= name;
        this.sex = sex;
    }
    public People(){

    }
}
 // 创建没有指定泛型的对象 ,它默认是Object类型
        People  obj= new People();
        obj.setName("李四");
        System.out.println(obj);
        System.out.println(((String)obj.getName()).length());

        // 创建泛型类的对象
        People<String> people = new People<String>("张三","男");
        System.out.println(people);
        System.out.println(people.getName().length());

定义泛型的字母

T : Type: 变量类型

K: Key : 任意键的类型

V: Value : 任意值的类型

E:ELement 用于定义集合的元素类型

2.2 泛型接口(generic interface)

在接口中定义泛型,使接口的方法可以使用该泛型,实现类实现该接口时需要指定接口的类型、

语法:

public interface Genarator<T> {
    public T getValue();

    public void setValue(T s);


}
public class StringGenarator implements  Genarator<String> {
   private String name;

    @Override
    public String getValue() {
        return name;
    }

    @Override
    public void setValue(String s) {
        this.name=s;
    }
public class StudentGenarator implements Genarator<Student> {
    private Student  stu;

    @Override
    public Student getValue() {
        return stu;
    }

    @Override
    public void setValue(Student s) {
        this.stu = s;
    }
}

泛型接口的好处:

让接口的方法的返回值或参数类型 也参数化 (泛型)

2.3 泛型方法

a、为什么会使用泛型方法

当一个类中 只有某个方法需要使用泛型,而不是类的全部方法使用泛型,这时可以将泛型定义的范围缩小,通常我们可以定义进行泛型方法。

b、定义泛型方法

语法:

 public  class 普通类{
      
      public <T>  T  getValue(){
          
      }
      
      public <T> void setValue(T t){
          
      }  
      
  }
public class Convert {
    /**
     * 转成字符串的方法
     * @param <T> : 任意类型

     * @return
     */
    public <T> String convertString(T t){
        return  t.toString();
    }

    public <K,V> V converted(K k){
        return (V)k;// 强转的前提 是k -v 有关系
    }

泛型的好处:

1、 可以对类的数据类型 写通用类型,提高代码的复用性 和 可扩展性

2.4 泛型通配符

在定义泛型时除了可使用大写字母表示一种泛型类以外,还可以使用通配符表示泛型类型,如下三种表示方法

<?> :表示一种通用的泛型类,与<T>相似

<? extends T> :表示 泛型类型是T的子类,或者是T

<? super T> : 表示泛型类型是T的父类,或者是T

问题: <?> 与<T> 的区别

 T t = new T() // 语法满足
  ? t = new ?()  // 语法不满足

<T> 是一种确定的类型 , 可以表示定义泛型类或泛型方法

<?> 是一种不确定的类型, 不能定义泛型类或泛型方法, 通常用于作为方法的形参

public class Dept<T> {
    // 第一个员工
     private T first;
     // 第二个员工
     private T second;
public class Employee {
    private String ename;

    public String getEname() {
        return ename;
    }
public class Manager extends  Employee {

    // 通过经理对象 给经理赋值名称
    public Manager(String ename){
        super(ename);
    }
// 使用不确定的泛型类型 <?>

    /**
     *
     * 这里的部门的泛型可以是任意类型
     */
    public void showInfo(Dept<?> dept){

        System.out.println(dept.getFirst());

    }

    /**
     * @param dept 的泛型可以是Employee  或者继承自Employee
     * @param dept
     */
    public void showInfo2(Dept<? extends Employee> dept){

        System.out.println(dept.getFirst());
        System.out.println(dept.getSecond());

    }

    /**
     *
     * @param dept 的泛型必须是 Manager 或者 Manager的父类
     */
    public void showInfo3(Dept<? super Manager> dept){

        System.out.println(dept.getFirst());
        System.out.println(dept.getSecond());

    }

    public static void main(String[] args) {
         TestDept obj = new TestDept();

         //创建部门对象
        Dept<String> dept = new Dept();
        dept.setFirst("员工1");
        dept.setSecond("员工2");
         obj.showInfo(dept);

         // 在部门中添加 员工对象
        Dept<Employee> dept2 = new Dept();
        dept2.setFirst(new Employee("小强"));
        dept2.setSecond(new Employee("小花"));
        //这里的dept2的泛型是 Employee
        obj.showInfo2(dept2);

        Dept<Manager> dept3 = new Dept();
        dept3.setFirst(new Manager("张经理"));
        dept3.setSecond(new Manager("王经理"));
        //这里的dept3的泛型是  Manager
        obj.showInfo2(dept3);

        //  调用时 参数的泛型必须是 Manager 或Manager的父类
        obj.showInfo3(dept3);
        obj.showInfo3(dept2);
    }

十二、集合框架

1、为什么会有集合?

存储多个元素我们以前学过数组类型, 由于数组类型特点是 相同类型且长度固定 ,如果需要存储某一天的新闻数据,用数组不合理 ,无法确定当天数量。 Java中提供可变长度的存储多个元素的数据类型,还可以存储不同数据结构的数据。这样的类型 就是“集合类型”

数组和集合的区别?

a、数组的长度固定,集合的长度可自动扩容

b、数组的数据类型固定,集合可以存储任意类型 ,集合可以支持泛型

c、数组没有方法,而集合提供大量的方法

d、Java中提供一个动态数组 集合类型,或其他结合类型

2.1集合的顶级接口: Collection

Collection属于单列集合的根接口,它扩展的主要子接口包括 java.util.List 和 java.util.Set接口,

List接口特点存储有序 且 可重复的元素, 而Set接口特点存储无序且不可重复的元素,其中List下扩展常用的实现类包括 java.util.ArrayList 和java.util.LinkedList 和Vector , 其中Set接口下扩展的实现类包括 java.util.HashSet 和 java.util.TreeSet .

集合接口的常用方法:

  • public void add(E) : 把给定的元素添加到集合中

  • public void clear():清空集合中的所有元素

  • public boolean remove(E):删除集合中指定的元素,删除成功返回true

  • public boolean contains(E):判断该元素是否存在集合中

  • public boolean isEmpty():判断是否为空集合对象 null会报异常

  • public int size():获取几个元素的大小

  • publict Object toArray() : 将集合元素转成对象数组

public static void main(String[] args) {
           //通过接口创建实现类 , 可指定存储的泛型
  
          Collection<String> collection = new ArrayList<String>();
          // 集合中指定了元素的类型  String
          collection.add("hello");  // 默认添加到末尾
          collection.add("hi");
          collection.add("哈哈");
          System.out.println("元素大小:"+ collection.size());
          // 删除集合元素  (后面的原始往前 移动)
          collection.remove("hi");
          System.out.println("元素大小:"+collection.size());
          System.out.println("第一个元素:"+((ArrayList<String>) collection).get(0));
          System.out.println("第二个元素:"+((ArrayList<String>) collection).get(1));
  
          // 判断元素是否存在
          System.out.println("是否存在哈哈:"+collection.contains("哈哈"));
          // 转成数组对象
          Object [] objs = collection.toArray();
          //遍历元素
          for(Object obj : objs){
              System.out.println("数组的元素:"+obj);
          }
          //清空元素  clear
          collection.clear();
          // 大小
          System.out.println("清空后元素的大小(对象依然存在,只能内容为空)"
                  +collection.size());
          // 判断对象中是否是空集合
          System.out.println(collection.isEmpty());
  
        
      }

Iterator 集合遍历接口

// 直接对集合元素遍历   泛型只能是包装类
          Collection<Integer> scores = new ArrayList<>();
          scores.add(90);
          scores.add(88);
          scores.add(92);
          scores.add(91);
          //遍历集合  使用   ,
          // 再遍历集合时 不能一边遍历集合一边删除集合元素,这样会改变它的遍历的模式
          Iterator<Integer> is = scores.iterator();
          //判断是否有下一个元素   ,如果true ,则可以通过next获取值 
           while(is.hasNext()){
               Integer score = is.next();
               System.out.println(score);
           }
  
  •  

    2.2 ArrayList类

    java.util.ArrayList是一个数组结构的集合,实现动态数组的功能,扩展所有Collection的方法

    数组结构的本质: 线性结构的顺序结构,ArrayList中使用连续的内存空间存储, 访问时通过下标(元素所在的位置)访问

  •  

    2.2 ArrayList类:

    java.util.ArrayList是一个数组结构的集合,实现动态数组的功能,扩展所有Collection的方法

    数组结构的本质: 线性结构的顺序结构,ArrayList中使用连续的内存空间存储, 访问时通过下标(元素所在的位置)访问

    ArrayList的数据结构

      分析一个类的时候,数据结构往往是它的灵魂所在,理解底层的数据结构其实就理解了该类的实现思路,具体的实现细节再具体分析。

说明:底层的数据结构就是数组,数组元素类型为Object类型,即可以存放所有类型数据。我们对ArrayList类的实例的所有的操作底层都是基于数组的。

public static void main(String[] args) {
         //  通过ArrayList 创建集合对象
        // 还可以存储自定义对象  默认容量是 10
        ArrayList<String> list = new ArrayList<String>();
        // 存储有序集合
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        // 将元素插入到指定位置
        list.add(1,"ddd");
        //直接 遍历元素  get(Index) 通过下标访问元素
        for(int i = 0 ;i<list.size();i++){
            System.out.println("集合元素:"+ list.get(i));
        }
        // 设置集合的最小容量
        list.ensureCapacity(20);



    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值