自学javase的回顾(3/5)


回顾第三天,持续更新…

1、类方法扩展和数组

类方法扩展:equals方法
当需要进行判断两个对象之间属性之间是否相等的时候,如果用equals进行判断,就会出现内存地址的比较。

public class Test {
    public static void main(String[] args) {
        Person p1=new Person("张三");
        Person p2=new Person("张三");
        System.out.println(p1.equals(p2));//false
    }
}
class Person{
    String name;
    public Person(String name) {
        this.name = name;
    }
}

在现实当中,false结果是不合理的,所以正常情况下,需要重写equals方法。

	@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(name, person.name);
    }

当两个内存地址相同的时候,返回true;如果比较的这个对象为null或者对象o不属于这个类,则返回false。将对象o转换为Person类的对象,然后比较属性。这里比较字符串也是调用了String类写好的equals方法。因为字符串比较不能使用双等号,字符串的创建也是对象的创建。
大结论:凡是基本数据类型的比较可以使用双等号进行比较。引用数据类型不能使用双等号进行比较,要使用equals方法进行比较。

toString方法:
凡是System.out.println(“字符串”),实际上都是System.out.println(“字符串”.toString()),而字符串对象在类体里面写好了toString方法,所以在终端上看到的是字符串的输出,如果输出一个对象,而这个对象没有重写toString方法,就会出现在终端的是类名@对象的内存地址:

public class Test {
    public static void main(String[] args) {
        Person p1=new Person("张三");
        System.out.println(p1);//Person@2d98a335
    }
}
class Person{
    String name;
    public Person(String name) {
        this.name = name;
    }
}

上述结果并不符合正常逻辑,所以一般情况下,需要重写toString方法:

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

finalize方法:
这个方法是超类Object中的方法,它的源代码是protected void finalize() throws Throwable{},它是垃圾回收机制的方法,如果想要在垃圾回收机制回收对象的时候执行什么语句,就可以在重写这个方法,加上想要执行的代码块。

public class Test {
    public static void main(String[] args) {
       for(long i=0;i<100000000;i++){
           Person p=new Person();
           p=null;
       }
    }
}
class Person{
    String name;
    @Override
    protected void finalize() throws Throwable {
        System.out.println("对象已销毁");
    }
}

hasCode方法:
它调用了底层去将对象的内存地址经过哈希算法转换成数值的方法。

public class Test {
    public static void main(String[] args) {
        Person p=new Person();
        System.out.println(p.hashCode());//764977973
    }
}
class Person{
    String name;
}

匿名内部类:
什么是内部类?
类方法中定义了一个新的类,这个类被称为内部类。例如在类中定义接口的新类。
什么是匿名内部类?
局部内部类的一种,直接new 接口的方法去定义接口的方法

public class Test {
    public static void main(String[] args) {
        Sum s=new Sum();
        int c=s.add(new Mymath() {
            @Override
            public int sum(int a,int b) {
                return a+b;
            }
        },100,200);
        System.out.println(c);//300
    }
}
interface Mymath{
    int sum(int a,int b);
}
class Sum{
    public int add(Mymath my,int a,int b){
        int c=my.sum(a,b);
        return c;
    }
}

数组:
数组是方便程序员储存数据的空间。
数组有以下特点:
1、数组只能存储一种数据类型的数据
2、数组中尽量不要存储大数据量的数据
3、一旦创建了数组,数组的长度不可变
4、数组存储的对象内存地址是连续的,因为连续和每个元素所占空间大小一致,通过数学计算之后,检索效率高。又因为内存地址连续,所以删除或者增加某个元素都会发生较大的变动,增删的效率较低。但是删除和增加最后一个元素没影响。
5、数组也是一个对象,它的内存地址是第一个元素的内存地址
如何初始化一个一维数组?
静态初始化语法:类型[] 数组名={元素,元素};
动态初始化语法:类型[] 数组名=new 类型[元素的个数];(它的元素的值都为null,需要自己手动赋值)
如何初始化一个二维数组?
什么是二维数组?
一个数组中的元素都是一维数组,这个数组被称为二维数组。
静态初始化语法:类型[][] 数组名={{元素,元素},{元素,元素}};
动态初始化语法:类型[][] 数组名=new 类型[元素的个数][一维数组元素的个数];

public class Test {
    public static void main(String[] args) {
        int[] i={7,4,8};
        int[] i1=new int[3];
        int[][] i2={i,i1};
        int[][] i3=new int[2][2];
    }
}

如何去遍历这些数组?
这里会有两种遍历数组的方式:
1、for循环

public class Test {
    public static void main(String[] args) {
        int[] i={7,4,8};
        int[] i1=new int[3];
        int[][] i2={i,i1};
        int[][] i3=new int[2][2];
        print(i);// 7 4 8
        System.out.println();
        print(i1);// 0 0 0
        System.out.println();
        print(i2);// 7 4 8 0 0 0
        System.out.println();
        print(i3);// 0 0 0 0
    }
    public static void print(int[] i){
        for(int c=0;c<i.length;c++){
            System.out.print(" "+i[c]);
        }
    }
    public static void print(int[][] i){
        for(int c=0;c<i.length;c++){
            for(int c1=0;c1<i[c].length;c1++){
                System.out.print(" "+i[c][c1]);
            }
        }
    }
}

2、foreach循环
什么是foreach循环,这是一种更加便利的循环工具,循环出数组或者集合中的每一个元素
语法:for(元素的类型 遍历的变量名:数组或者集合名){
System.out.println(遍历的变量名);
}

public class Test {
    public static void main(String[] args) {
        int[] i={7,4,8};
        int[] i1=new int[3];
        int[][] i2={i,i1};
        int[][] i3=new int[2][2];
        for(int i4:i){
            System.out.println(i4);// 7 4 8
        }
        for(int[] i5:i2){
            for(int i6:i5){
                System.out.println(i6);// 7 4 8 0 0 0
            }
        }
    }
}

数组扩容:
由于数组创建之后不可改变长度的特短,所以扩容就是创建一个更大的新数组,将旧数组传入新数组的过程叫做数组扩容。数组扩容是System的方法。
语法:System.arraycopy(旧数组名,拷贝旧数组的下标,新数组名,拷贝到新数组的下标,元素的个数);

public class Test {
    public static void main(String[] args) {
        int[] i = {7, 4, 8};
        int[] i2=new int[5];
        System.arraycopy(i,0,i2,0,3);
        for(int i3:i2){
            System.out.println(i3);//7 4 8 0 0
        }
    }
}

数组增删:
由于数组长度不可变的特点,和数组扩容采用同一原理进行增删。也可以将数组转换为集合,再调用集合的remove方法。

2、排序方法和查找方法

数组的排序有sort方法,sort方法是Arrays的方法。

public class Test {
    public static void main(String[] args) {
        int[] i = {7, 4, 8};
        Arrays.sort(i);
        for (int i5 : i) {
            System.out.println(i5);// 4 7 8
        }
    }
}

数据的两种常见排序方法:
1、冒泡排序法
int[] i={5,2,4,6,1};
冒泡排序这里是采用了两两元素根据大小然后相互对调的方法。
每一次循环都要找出最大的元素放到最右边。然后取出最右边的元素
第一次循环:2,4,5,1,6
第二次排序:2,4,1,5
第三次循环:2,1,4
第四次循环:1,2
第五次循环:1
倒着取出所有最右边的元素:1,2,4,5,6
冒泡排序的规律:元素的个数为n,总共需要循环n次,每次循环需要对调n-1次,对比也是n-1次。

public class Test {
    public static void main(String[] args) {
        int[] i = {5,2,4,6,1};
        for(int i1=i.length;i1>0;i1--){
            for(int i2=0;i2<i1-1;i2++){
                if(i[i2]>i[i2+1]){
                    int y=i[i2];
                    i[i2]=i[i2+1];
                    i[i2+1]=y;
                }
            }
        }
        for(int i3:i){
            System.out.println(i3);//1 2 4 5 6
        }
    }
}

2、选择排序法
int[] i={5,2,4,6,1};
选择排序是每次循环找出最小的元素放到最左边
第一次循环:1,2,4,6,5
第二次循环:2,4,6,5
第三次循环:4,6,5
第四次循环:5,6
第五次循环:6
每次循环取出最右边的元素:1,2,4,5,6
选择排序的规律:元素的个数为n,总共需要循环n次,每次循环对调1次,对比n-1次。

public class Test {
    public static void main(String[] args) {
        int[] i = {5,2,4,6,1};
        for(int i1=0;i1<i.length;i1++){
            int min=i1;
            for(int i2=i1+1;i2<i.length;i2++){
                if(i[i1]>i[i2]){
                    min=i2;
                }
            }
            if(min!=i1){
                int y=i[min];
                i[min]=i[i1];
                i[i1]=y;
            }
        }
        for(int i3:i){
            System.out.println(i3);//1 2 4 5 6
        }
    }
}

数据查找一般来说有两种查找方法:
1、挨个查找
int[] i={5,2,4,6,1};
例如想找元素为4的下标,挨个查找就是这样的。

public class Test {
    public static void main(String[] args) {
        int[] i = {5, 2, 4, 6, 1};
        for (int i1=0;i1<i.length;i1++){
            if(i[i1]==6){
                System.out.println(i1);//3
            }
        }
    }
}

2、二分法查找
int[] i={1,2,4,5,6};
二分法查找是对半查找,这个查找方法是基于顺序从小到大排好的查找方法。先记下第一个元素的下标和最后一个元素的下标,这两个下标加和除以二,得到的这个数字就是数组的中间的那个元素的下标,寻找的元素就是从中间开始找,如果查找元素大就往右边查找,然后再次从右边的中间那个元素开始找…例如想找元素为6的下标:
第一次寻找:4,5,6
第二次寻找:5,6
第三次寻找:6

public class Test {
    public static void main(String[] args) {
        int[] i={1,2,4,5,6};
        int index = binarySearch(i,6);
        System.out.println(index);//4
    }
    public static int binarySearch(int[] i1,int i){
        int begin=0;
        int over=i1.length-1;
        int mid=(begin+over)/2;
        while (begin<=over){
            if(i==i1[mid]){
                return mid;
            }else if(i>i1[mid]){
                begin=mid+1;
                mid=(begin+over)/2;
            }else if(i<i1[mid]){
                over=mid-1;
                mid=(begin+over)/2;
            }
        }
        return -1;
    }
}

Array工具:
1、sort工具:进行数组排序
2、binary工具:进行数组查找(基于排序好的数组),查找的那个元素如果不存在则返回-1。

public class Test {
    public static void main(String[] args) {
        int[] i3={5,2,4,6,1};
        Arrays.sort(i3);
        int index =Arrays.binarySearch(i3,6);
        System.out.println(index == -1 ? "该元素不存在" : "该元素下标是" + index);//4
    }
}

综上所述,选择排序的对调次数比冒泡排序次数少,所以选择排序的效率更高一些。

3、字符串对象方法和包装类

java.lang.String
在java中使用双引号括起来的都是String对象,字符串一旦创建就无法被改变,因为被final修饰了,双引号的字符串和其他对象不同,它的创建存储在方法区的字符串常量池中。
String i=“abc”;这里的i是指向字符串常量池中的abc的内存地址。
String的构造方法:参数可以是字符串对象、char[]、byte[]等

public class Test {
    public static void main(String[] args) {
        char[] c={'a','b','c'};
        String i=new String(c,1,2);
        System.out.println(i);//bc
    }
}

下面是字符串常见的方法

public class Test {
    public static void main(String[] args) {
        char c="中国人".charAt(1);//索引下标的字符
        System.out.println(c);
        int c1="abv".compareTo("abc");
        System.out.println(c1);//对比两个字符串
        System.out.println("Hello".contains("He"));
        //判断字符串是否存在包含关系,返回值为boolean
        System.out.println("Hello".endsWith("lo"));
        //判断字符串是否是以后面的字符串为结尾的,返回值为boolean
        System.out.println("Hello".equals("Hello"));
        //判断字符串是否相等
        System.out.println("Hello".equalsIgnoreCase("hello"));
        //判断字符串是否相等,并且忽略大小写
        byte[] c2="acv".getBytes();
        //将字符串返回成byte数组
        for(int i=0;i<c2.length;i++){
            System.out.println(c2[i]);
        }
        System.out.println("Hello".indexOf("lo"));
        //子字符串在此字符串中第一次出现的索引
        String c4="";
        System.out.println(c4.isEmpty());
        //判断字符串是否为空串
        System.out.println("abc".length());
        //字符串的长度
        System.out.println("llolloll".lastIndexOf("ll"));
        //最后出现的索引
        System.out.println("Hello".replace("l","o"));
        //替代字符串
        String[] str="1990-10-1".split("-");
        //以指定的字符为分隔符来进行分割,以数组的形式接受
        for(int i=0;i<str.length;i++){
            System.out.println(str[i]);
        }
        System.out.println("Hello".startsWith("He"));
        //判断是否以某个字符串为开始
        System.out.println("Hello".substring(3));
        //以下标元素开始输出字符串
        char[] chars="Hello".toCharArray();
        //将字符串转换成char数组
        for(int i=0;i<chars.length;i++){
            System.out.println(chars[i]);
        }
        System.out.println("HELLO".toLowerCase());
        //将字符串中的大写转换成小写
        System.out.println("hello".toUpperCase());
        //将字符串中的小写转换成大写
        System.out.println("  da".trim());
        //去空白的
        String i=String.valueOf(10);
        //转换字符串
        System.out.println(i);
    }
}

StringBuffer和Stringbuilder
都是字符串拼接的工具,为什么不使用+来拼接,因为字符串的字符是不可变的,每次创建String对象都要消耗大量内存,效率低,而这两个就是在字符串常量池中创建byte[]数组,是可变的,效率高。它的初始化容量是16为了效率,最好预先给一个合适的容量。
StringBuffer是线程安全的
StringBuilder是非线程安全的

public class Test {
    public static void main(String[] args) {
        StringBuffer s=new StringBuffer(100);
        s.append("i");
        s.append(97);
        System.out.println(s);//i97
    }
}

包装类:
java中为8种数据类型又对应的准备了8种包装类型。8种包装类属于引用数据类型。
为啥要提供8中包装类呢?
有时候方法中的参数想要一个类的对象,而基本数据类型不符合
所以要准备8种包装类
基本数据类型 包装类
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)
其中有6种的父类都是Number类,Number是一个抽象类
自从jdk1.5之后就有了自动装箱和自动拆箱。
自动装箱就是指将基本数据类型转换成包装类,拆箱与之相反
Interger有几个常用的方法:
1、toBinaryString()、toHexString()、toOctalString()转换进制
2、parseInt()将类型转换成int

注意:Integer这个对象如果调取[-128~127]之间的整数,就不需要通过new对象,引用直接去引用方法区的整数型常量池,而不在这个范围,就需要去在堆中new对象

public class Test {
    public static void main(String[] args) {
        Integer i=900;
        Integer i2=900;
        System.out.println(i==i2);//false
        Integer i3=127;
        Integer i4=127;
        System.out.println(i3==i4);//true
    }
}

4、日期和数据

BigDecimal:
java.math.BigDecimal
这个处理大数据使用的数学工具,精度极高,适用在银行等场景。

public class Test {
    public static void main(String[] args) {
        BigDecimal b1=new BigDecimal(22.834234234);
        BigDecimal b2=new BigDecimal(234.4564523);
        BigDecimal b3=b1.add(b2);
        System.out.println(b3);//257.29068653399999533348818658851087093353271484375
    }
}

import java.text.DecimalFormat
这个是处理数字的格式化工具

public class Test {
    public static void main(String[] args) {
        DecimalFormat d=new DecimalFormat("####,###.##");
        String i=d.format(12323441.31);
        System.out.println(i);//12,323,441.31
    }
}

java.util.Random:
这个是关于随机数的工具

public class Test {
    public static void main(String[] args) {
        Random r=new Random();
        int i=r.nextInt(6);
        System.out.println(i);//从0-5的随机整数,不包括6
    }
}

Date:
java.util.Date
这个是处理日期的工具。
java.text.SimpleDateFormat
这个是对日期格式的处理工具。

public class Test {
    public static void main(String[] args) {
        Date date=new Date();
        System.out.println(date);//Fri Jul 03 17:59:18 CST 2020
        SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:sss");
        String date1=s.format(date);
        System.out.println(date1);//2020-07-03 17:59:18:005
    }
}

有了时间转换为字符串,那么字符串如何转换为时间呢?
parse方法,是SimpleDateFormat对象的方法。

public class Test {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:sss");
        Date date=s.parse("2000-12-20 24:23:34:340");
        String s1=s.format(date);
        System.out.println(s1);//2000-12-21 00:28:40:040
    }
}

System.currentTimeMillis方法,返回值是long类型。这个方法是计算出从1970年1月1日到现在的时间总和,单位是毫秒。这个方法可以计算出程序执行的时间。在程序开始的时候减去结束的毫秒数,就是程序执行的时间。

public class Test {
    public static void main(String[] args) {
        long begin=System.currentTimeMillis();
        for(int i=0;i<100;i++){
            System.out.println(i);
        }
        long over=System.currentTimeMillis();
        System.out.println(over-begin);//2
    }
}

5、枚举和异常

枚举:
什么是枚举?
字面意思来说就是列出所有成员的意思。在java中是指定返回值数目和具体内容。关键字:enum
语法:enum 枚举名{}

public class Test {
    public static void main(String[] args) throws ParseException {
        System.out.println(grade(70));//优秀
    }
    public static 状态 grade(int mark){
        if(mark<60){
            return 状态.;
        }
        else if(mark>60&&mark<70){
            return 状态.一般;
        }
        else {
            return 状态.优秀;
        }
    }
}
enum 状态{,一般,优秀;
}

异常:
什么是异常?
一般来说,系统在处理代码过程有三种结果:正确编译通过、代码和环境错误(Error)、逻辑错误(Execption)。
代码和环境错误就是语法错误和运行环境不正确,而逻辑错误就是属于逻辑层面的,例如空指针异常、数组下标越界。这些逻辑错误就是异常,是可以通过程序改写来解决的。

异常分为两种异常:
1、编译时异常(ExecptionSubClass以及它的子类):
编译时异常并不是编译时出现的异常,是程序员在编译前必须对这种异常做预先处理,如果没有做处理,就会报错。
2、运行时异常(RuntimeExecption以及它的子类)
运行时异常,是在运行阶段出现的异常,程序员可以对其做预处理,也可以不做。

错误的改正过程就是修改代码逻辑不正确或者语法不对的地方等等。
异常改正的过程为两种:
1、throws抛出异常(交给上级去处理,属于推卸责任,如果上级没办法解决就会报错)
2、try…catch捕捉异常(自行处理,尝试…抓住)
一般情况下,不建议main方法去throws异常,因为JVM处理不了的话,就只能总结程序。
try语句块中处理,如果出现异常,就不执行try语句块,去执行catch语句块。
跟随try…catch语句块的还有一个语句块是finally,这个语句块是最后执行的,在IO流中文件的流要关闭的情况下,就会用到finally语句块。

异常也可以程序员自己定义:

public class Test {
    public static void main(String[] args) {
        String s="asdf";
        MyException exception=new MyException("长度不正确");
        if(s.length()!=3){
            exception.printStackTrace();
        }else{
            System.out.println("长度正确");
        }
    }
}
class MyException extends Exception{
    public MyException() {
    }
    public MyException(String message) {
        super(message);
    }
}

y异常警告

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值