@future

Java-总结

2023-11-15  本文已影响0人  不返y

1.Lambd表达式

Lambda表达式是简洁化的语法定义代码块。目的是弥补Java无法函数式编程的缺点。用其可以的进行代码块的传递,使代码更加简洁。

注意:使用Lambd表达式实现的接口一定是函数式接口(@functional interface)。但这个函数式接口并不用记,应为它基本上也没有什么用,只需要记忆哪个方法需要传递一段怎样的代码实现功能,如下面这段代码是用了表达式n->n==1

ArrayList<Integer> list = new ArrayList<>();
list.add(3);
list.add(1);
list.add(2);
list.removeIf(n->n==1);//简便运算,其实不需要知道函数式接口的概念,直接当成函数块使用就行
System.out.println(list);

前面的n是表示一个形参,后面的n==1是一个条件,表示 如果集合中的元素满足这个条件就把元素从集合中删除。

他在Java中实际是一个匿名内部类的形式,只不过是代码看起来简洁了而已,如果把它还原了,它是:

list.removeIf(new Predicate<Integer>() {
            @Override
            public boolean test(Integer n) {
                return n==1;
            }
        });

再从原本的匿名内部类的形式,通过简化的方式一步步简化。

  1. 先把它写成标准的Lambd表达式,由形参Integer n,箭头->,和代码块{return false;}三部分组成。
list.removeIf ((Integer n)->{return false;});
  1. 表达式中形参的类型是可以推断出来的(和集合的类型一致),可以省略
list.removeIf ((n)->{return false;});
  1. 形参只有一个,外面的括号可以省略(注意:没有形参的也要写()表示空参,只有刚好一个参数才可以省略)
list.removeIf (n->{return false;});
  1. 如果代码块内的代码只有一行,可以直接写这一行(return不用写)
list.removeIf (n->n==1);

这样就一步步简化成了这样了,其实写的时候只需要知道可以简化的地方,然后直接写最终结果就可以,这样可以使代码更加简洁,但他的本质还是匿名内部类。

如果传递的函数是想实现某个已经实现的功能,可以使用::(双冒号)引用对应的方法。

2.什么是多态

Java三大核心思想之一,就是指子类的对象可以赋值给父类的变量(向上转型,就是指子类可以使用父类的名字),但在使用的过程中有一些注意事项:

如果子类使用父类的名字

  1. 只能获取到父类的成员变量
  2. 只能使用父类的成员方法(但是实际执行的还是子类的方法,只是无法使用子类中新创建的方法)

如果要使用子类的特有变量和方法,就必须将子类的对象强制类型转换(也就是向下转型)回到子类。

3.黑窗口运行Hello world

public class Text {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
  1. 使用记事本写入上述代码
  2. 打开cmd,输入javac Text.java 编译(注意此处一定要写.java后缀)
  3. 输入java Text翻译运行程序 (注意此处不要写.class后缀)

4.引用数据类型

基本数据类型有(四类八种)

  1. 整型

    1. byte 8 = 1*8(1字节8位)
    2. short 16 = 2*8(2字节16位,下面类似)
    3. int 32 = 4*8
    4. long 64 = 8*8
  2. 浮点型

    1. float32 = 4*8
    2. double64 = 8*8
  3. 布尔型

    boolean布尔类型,只有两个值 truefalse

  4. 字符型

    char 用来存储单个字符,用单引号包围。

除了以上基本数据类型以外的所有类型都是引用数据类型,典型的有String字符串和enum枚举常量

5.关于foreach

也叫做增强For,格式如下:

for(内部变量类型 内部变量名 : 数组或者集合名)
{
    //代码
}

如:

  1. 数组遍历
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i : arr) {
    System.out.println(i);
}
  1. 集合遍历
//ArrayList<Integer> list
for (Integer integer : list) {
    System.out.println(integer);
}

foreach是普通for的简化版,没有了索引与结束条件。使代码更加简化。但是要注意foreach遍历基本数据类型时,用的是临时变量存储其数据,不能修改基本数据类型的数据。如:

int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i : arr) {
    i = 0;
}

这个赋值是错误的,修改的仅仅是 i 这个临时变量,并没有修改arr数组的内部,最后的数组仍然是arr = {1, 2, 3, 4, 5, 6, 7, 8, 9}

6.Scanner获取数据的方法

Scanner sc = new Scanner(System.in);System.in 标准输入流,控制台的输入
sc.next数据类型()读取对应数据类型,返回指定数据,以 '指定数据后的空白字符' 为终止,前面的空白字符自动过滤
sc.next()读取数据,以 '数据后的空白字符' 为终止,前面的空白字符自动过滤,返回String
sc.nextLine()读取一行,回车结束,返回String

为了确保输入正确,一般来说sc.nextLine()与前面的方法不混合使用。

7.java可编译的两种程序类型

8.排序对象

  1. 如果是数组排序

    使用数组工具Arrays.sort()

  2. 如果是集合排序

    使用集合的处理工具Collections.*sort*();,也可以直接调用集合内的sort方法集合.sort()

一般排序方式是使用快速排序,默认为顺序排序,也可以自己实现比较器Comparator接口,实现函数,提供比较方法,自定义排序

9.常用容器

  1. ArrayList

    最常用的容器,有索引,有序,可重复

  2. HashSet

    无索引,无序,不可重复

  3. TreeSet

    无索引,有序,不可重复,方便增删查改,但是添加时的效率不高,底层采用数组哈希表、链表以及红黑树。

  4. HashMap

    键值对,键是唯一的,键与值一一对应,值可以重复

  5. TreeMap

    键值对,键是唯一的,键与值一一对应,值可以重复,方便增删查改,但是添加时的效率不高

10.抽象类

  1. 抽象类的定义是为了声明类里面至少有一个抽象方法。

  2. 抽象方法是没有确定下来的方法,没有函数体,只有函数的名字参数以及返回值,需要子类继承后重写来进行实现。

  3. 不可直接调用抽象方法,不可直接创建抽象类的对象。抽象类的子类要么重写所有的抽象方法,要么也声明为抽象类。(如果希望子类可以不用实现某个方法,可以用default关键字修饰这个方法)

11.权限修饰符

(默认): 同一个包里的类可以访问

public: 最大的权限修饰符,公共的,任何地方都可以访问

private: 最小的权限修饰符,私有的,只有自己(本类)才能使用

protected: 为了解决private 一个问题(如果被private修饰,任何其他的类都不能访问,包括自己的子类),但是有时候我们又希望自己的子类也能访问,所以就出现了protected 。适用于不想让外界访问,但是希望子类继承的类型。

12.this和super为什么不能连用

这个问题我感觉有点问题,更详细的的问法应该是this和super的构造方法为什么不能连用。

这样一想其实就简单了,因为他们本身就有一层关系,在使用this的构造方法一般会默认执行super(),执行父类的初始化。你要是在用一个super(),不就是重复初始化了嘛。

13.Scanner为什么要关闭

使用完输入流,及时关闭可以释放内存、节约内存占用.但是一般Scanner是使用System.in进行输入,使用scanner.close方法相当于System.in.close()。关闭系统输入流,一般是不建议关闭,除非是你从这行代码之后再也不用系统的输入,即控制台输入。

14.异常处理

异常处理的的一般方式:try...catch(异常)...finally

try包含着的代码如果抛出了异常,会被catch捕获,执行catch内部的代码(异常解决方案)

catch捕获的前提是:catch括号内的异常包含抛出的异常,即catch括号内的异常就是抛出异常或者是抛出异常的父类(上级)。

此外,不管try内的代码有没有抛出异常,都会执行finally的代码。(如果抛出了异常会在catch代码执行完成后执行finally)

注:1. 如果要把retuen语句写在try...catch(异常)...finally异常处理体系中,需要在try和catch区域中分别写出return,

  1. 并且如果程序执行到try或者catch中的return时,如果有finally,会先执行finally内的代码,再去执行return,如下面的代码:
public static int function() {
        try{
            if (false) throw new RuntimeException(); //此处代表代码没有抛出异常
            return 1;
        }catch (RuntimeException e){
            System.out.print("catch,");
            return -1;
        }finally {
            System.out.print("finally,");
        }
}

这个函数的执行结果(print的输出的信息)是finally,返回值为1。


public static int function() {
        try{
            if (true) throw new RuntimeException(); //此处代表一个一定会报错的代码
            return 1;
        }catch (RuntimeException e){
            System.out.print("catch,");
            return -1;
        }finally {
            System.out.print("finally,");
        }
}

这个函数的执行结果是catch,finally,返回值为-1。


那么如果finally中也有return呢?(答:和前面的结论一样,他一定会从finally中的return返回,因为在程序执行到try或者catch中的return语句时,就会跳转到finally中,不管程序是否抛出异常,必然会先执行finally中的return)

private static int function() {
        try {
            if (true) {
                throw new RuntimeException();
            }
            return 1;
        } catch (RuntimeException e) {
            System.out.print("catch");
            return -1;
        } finally {
            System.out.print("finally");
            return 0;
        }
    }

这个函数的执行结果是catch,finally,返回值为0。

private static int function() {
        try {
            if (false) {
                throw new RuntimeException();
            }
            return 1;
        } catch (RuntimeException e) {
            System.out.print("catch");
            return -1;
        } finally {
            System.out.print("finally");
            return 0;
        }
    }

这个函数的执行结果是finally,返回值为0。

上一篇 下一篇

猜你喜欢

热点阅读