java日记


java基础

笔记内容学自链接视频:https://www.bilibili.com/video/BV12J41137hu

HelloWorld

  • java文件后缀 .java

  • java文件名要与类名一致

  • 全语言语法雷同

  • java大小写敏感,写代码注意大小写

  • java同时存在编译型和解释型

    简单说,编译型是先编译在执行,解释型是执行的同时进行编译(或者先执行后编译)

public class HelloWorld{
    public static void main(String[] args){
        System.out.print("Hello World!");
    }
}

编译

写好java文件,就该编译成字节码了,目的是把Java文件编译成JVM能够执行的Class文件。

本地编译也可,编译后可运行编译后文件,各大编程工具都会自动编译,记事本除外

image-20210702210424155

image-20210702210447907

编译与否,本地大抵就是这样

java基础语法

  • 注释:

    单行://

    多行:/**/

    文档:

    /**
    *
    */    
    

    /**开头*/结尾,中间每行以*开头

/**
 *                             _ooOoo_
 *                            o8888888o
 *                            88" . "88
 *                            (| -_- |)
 *                            O\  =  /O
 *                         ____/`---'\____
 *                       .'  \\|     |//  `.
 *                      /  \\|||  :  |||//  \
 *                     /  _||||| -:- |||||-  \
 *                     |   | \\\  -  /// |   |
 *                     | \_|  ''\---/''  |   |
 *                     \  .-\__  `-`  ___/-. /
 *                   ___`. .'  /--.--\  `. . __
 *                ."" '<  `.___\_<|>_/___.'  >'"".
 *               | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 *               \  \ `-.   \_ __\ /__ _/   .-` /  /
 *          ======`-.____`-.___\_____/___.-`____.-'======
 *                             `=---='
 *          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 *                     佛祖保佑        永无BUG
 *            佛曰:
 *                   写字楼里写字间,写字间里程序员;
 *                   程序人员写程序,又拿程序换酒钱。
 *                   酒醒只在网上坐,酒醉还来网下眠;
 *                   酒醉酒醒日复日,网上网下年复年。
 *                   但愿老死电脑间,不愿鞠躬老板前;
 *                   奔驰宝马贵者趣,公交自行程序员。
 *                   别人笑我忒疯癫,我笑自己命太贱;
 *                   不见满街漂亮妹,哪个归得程序员?
*/

标识符

  • 关键字:

image-20210702215742511

java组成部分如名字,类名,变量名,方法名都称为标识符

数据类型

java数据类型分基本类型和引用类型

基本类型

  • 整数:

    • 字节: byte 1B
    • 短整型:short 2B
    • 整形: int 4B
    • 长整形: long 8B

    为了便于区分,长整型要在数字后加字母L

    public class Heool{
        public static void main(String[] args){
            byte by = 20;
            short sh = 30;
            int in = 40;
            long lo = 50L;
        }
    }
    
  • 小数:浮点数

    • 单精度浮点型:float 4B
    • 双精度浮点型: double 8B

    两者的区别可以简单理解为float精度小,占内存少,double精度大,占内存多

    float型要在数字后加字母F

    public class Hello{
         public static void main(String[] args){
            float fl = 1.23F;
            double dou = 3.1415926;
        }   
    }
    
  • 字符

    字符型: char 2B

    字符型只能是一个字符,不能多定,使用时用单引号包裹,不能用双引号

    字符的本质是数字,例如:

    public class Hello{
     public static void main(String[] args){
         char ch = 'A';
         char ch1 = '\u0061';
         System.out.println((int)ch);
         System.out.println(ch1);
     }
    }
    //结果为 65  a 转义后为对应ascii值
    
  • bool(布尔)

    布尔型: boolean 1位

    布尔型的值只能是true或者false

    public class Hello{
        public static void main(String[] args){
            char ch = 'A';
            boolean boo = false;
        }
    }
    
  • 进制

    image-20210703101755126

    进制表示在数字前加相应标识符即可

转换

image-20210703110823669

从高容量类型转低容量会自动转换

从低容量到高容量要强制转换

计算后数据非父数据类型,要将一个数先强制转换为目标数据,防止出错

int a = 10;
int b = 20;
c = a / (double)b;

多个整形计算,如果有long类型,自动转换后类型一定为long,无long一定为int

多个浮点型计算,如果有double类型,自动转换后一定为double

转换会存在内存溢出和精度问题

public class num{    
    public static void main(String[] args){            
        float a = 13.9F;            
        double b = 3.14;            
        int c = 123;            
        System.out.println(a);            
        System.out.println(b);            
        System.out.println(c);            
        b = a;            
        c = (int)a;            
        System.out.println(b);            
        System.out.println(c);    
    }
}

image-20210703110408937

引用类型

new的一个类的变量即为引用类型

Demo03 demo03 = new Demo03();//Demo03即为引用类型

输出——print与println

println输出完毕会换行,print输出完不会换行

image-20210703100834360

变量

image-20210703111741309

变量三要素: 类型,变量名,作用域

作用域即变量作用范围

类变量和其他变量的区别是在类型前定义了静态 static

若没有对实例变量进行定义,基本类型初始为0,其他类型初始为null

public class Hello{    
    static String wu = "来打游戏吗?";    
    String gree = "拉个女孩子,一起打游戏?";        
    public static void main(String[] args){            
        String gile = "早啊";            
        System.out.println(gile);            
        Hello hello = new Hello();            
        System.out.println(hello.gree);            
        System.out.println(wu);            
        System.out.print("十点开黑,不见不散");    
    }
}

常量

image-20210703114056284

final为修饰符,不存在先后顺序

运算符

image-20210703114443442

之前其他语言学了,不做详细解释

位运算

说一下左右移

数据在计算机中以二进制存在,如

2 : 0000 0010

左移<<就是将2的二进制整体向左移动,右移向右

2<<1 : 0000 0100

image-20210703145645025

简单理解,左移乘二,右移除二

逻辑运算符

image-20210703145959688

Sring 后出现+,默认后面的所有类型为字符串

三元运算符

x ? y : z

如果x为真,使用y否则使用z

javadoc

doc指令

  • @author : 作者
  • @version:版本
  • @since: 开发版本

image-20210704144709477

/** 
* @author MUjie 
* @version 1.0 
* @since 13.0.2 
* 
*/
public class Doc {    
    String name;    
    /**     
    * @author Mujie     
    * @param name     
    * @return     
    */    
    public String test(String name) throws Exception{        
        return name;    
    }
}

java包机制

java的包就相当于命名空间,具体不解释

包中文件使用package 标识

image-20210703115049236

这样定义同名类就不会冲突

java的包机制还是比较特殊的,规定包名必须为倒置的域名,当然也可以不这么做

以src文件为项目根目录,就好像php是以www为根目录

目录格式:

目录格式

java语法

Scanner 类-接收用户输入

java在java.util中定义了获取输入的类

使用时需将Scanner类实例化

Scanner scanner = new Scanner(System.in);
//out表示输出,in表示输入

使用 hasNext 与 hasNextLine 判断是否还有输入的数据

使用next或nextLine接收用户输入

image-20210704155922324

hasNext和hasNextLine同理

next和nextLine

举个简单的例子

如果使用next得到输入,遇到空格就会停止,空格后面的数据不会接收

这时没有接收的数据仍在缓冲区中,若使用循环,会得到没有接收的数据

image-20210704160430832

可以看到,循环语句没有让我们再次输入

nextLine 遇回车结束,当写在循环中时,会再次让我们输出

image-20210704160707412

hasNext和hasNextLine

  • hasNext()方法会判断接下来是否有非空字符.如果有则返回true,否则返回false
  • hasNextLine() 方法会根据行匹配模式去判断接下来是否有一行(包括空行),如果有则返回true,否则返回false
Scanner scanner = new Scanner(System.in);
int i = 0;
while (i!=2) {
    if (scanner.hasNext()) {
        String str = scanner.nextLine();
        System.out.println(str);
    }
    i++;
}

如上述的代码

当写入

Hello【回车】

a【空格】h

Hello在hasNext和nextLine均判断通过,循环语句再次请求输入

【空格】h在hasNext时判断为结束,所以nextLine只接收到了空格,h仍在缓存区

image-20210704162206887

后面我再次测试,这个问题没有出现,输出了正常的【空格】h,所以具体原因没来的即探究

结论

获取输入时,需将next-hasnext 或nextLine-hasNextLine成对出现,否则有时会产生错误

其他的

除字符型String默认nextLine和hasNextLine外,指定其他输入的类型需要特别指明

如int型为nextLineInt,double为nextLineDouble

不指明会报错

image-20210704165203018

同时,除String可用Line得到外,其他类型数据均只能使用next+类型而不能使用nextLine

如果使用next获取数据后在缓存区留有数据的情况下关闭Scanner,程序会报错

image-20210704165655490

结构控制

顺序结构略

选择结构

语法:if(表达式){语句}

注意:比较String型不要使用==而是改用equals(译:与..相等)

public static void main(String[] args) {
    //从键盘接收数据
    Scanner scanner = new Scanner(in);
    String str = scanner.nextLine();
    scanner.close();
    if (str.equals("")) out.print("说点什么吧");
    else out.println(str);

}

这里推荐一个idea的快捷键ALT+ENTER

image-20210704173636532

可以快速修正代码,让代码简洁起来

if语句中定义的值只能在该if中使用,如果要做其他作业域使用,需要定义至相应作用域

image-20210704174930381

多级选择switch

语句:

switch(字符)
    case 字符:
        语句1;
    case 字符:
        语句2;
    default:
        语句3;
//break可选
//若case没有匹配到,执行def
//不使用break,会发生case穿透现象,即从匹配成功的开头输出下面所有选项
//JDK7后,表达式支持比较字符串

循环结构

基础

  • while 条件为真执行循环,先判断后执行
  • do-while 条件为真执行循环,先执行后判断(所以至少执行一次循环语句)
  • for(初始值;条件;迭代) 条件成立执行循环

遍历

语法:

//定义数组
int[] a = [0,10,20,30,40];
//遍历输出
for(int x:a){
    System.out.println(x);
}
//将a中的元素挨个复制给x,输出x

循环控制

break,continue

过于常用,不做解释

goto标签

java中没有被正式使用

字符串+:即为一个标签,用于跳回指定位置

outer:
for (int x : nums) {

    if (x == 40) continue outer;
    out.print(x + "\t");
}
//一般情况,可以写,没必要,和continue效果相似

image-20210704204759684

java方法

java语句解析

public class Kong {//定义一个属性是public的类,名为Kong    
    public static void main(String[] args) {    
        //定义一个属性是public的静态方法,名为main,执行结束后返回值为void(无返回值/不返回)      
    }    
    public int sum(int a;int b){    
        //定义一个属性是public的方法,名为sum,传入两个整数a,b,执行结束后返回一个int类型数据        
        return 10; //返回10    
    }
}

调用

int sum = sum(2,3);out.println(sum);}public static int sum(int a,int b){    return a+b;}//输出5

image-20210704215153747

image-20210704220352425

如果方法有返回值,方法调用通常当作一个值处理

如果返回空,则用语句调用

形参和实参

  • 形参:在程序中定义的参数,相当于占位符
  • 实参:实际传入的参数

方法重载

java可以定义名称相同参数不同的方法,以达到在不同类型中调用的目的

image-20210705093830578

image-20210705093914366

可变传参

当需要传入很多参数时,直接定义会很繁琐,这时需要用到可变传参

语句:

public int num(int a,int...b){}

int...b即为可变传参,可以接收任意的个数的值

可变传参必须定义在所有形参之后

递归

递归即自己调用自己

递归要求两个条件

递归边界:递归必须有界限,不能一直执行下去

递归体:递归的语句

public class Main {    
    public static void main(String @NotNull [] args) {        
        for (String x : args) System.out.println(x);        
        Scanner scanner = new Scanner(System.in);        
        int n = scanner.nextInt();        
        System.out.println(fo(n));    
    }
    public static int fo(int n)    {        
        if (n < 1) System.out.println("错误的输入");        
        if(n == 1) return 1;        
        else return n * fo(n - 1);    
    }
}

java数组

定义数组

String[] num;//创建/声明一个数组num = new String[10];//声明该数组有十个值

或者写一起

String[] num = new String[10];

如果直接赋值,则无需使用new声明

int[] num = {10,1,1,1,1};

数组是一个对象,可以使用引用类型定义

所有new的都是对象

二维数组

int[][] array = {{1,2,3},{2,3,6}};

Arrays类

java在java.uitl中提供了对数组的支持,这里简单举例几个常用的方法

Arrays.toString(a);//打印数组a
Arrays.sort(a);//对数组a升序排序
Arrays.fill(a,1,3,0)//将数组中从第2到第3个数填充为0(左闭右开)

image-20210705211656347

冒泡排序

import java.util.Arrays;
import static java.lang.System.out;
public class Plex {    
    public static void main(String[] args) {        
        int[] b = {1, 3, 2, 67, 3, 645, 234, 13, 23}; //定义要排序的数组        
        out.println(Arrays.toString(num(b))); //输出新数组    
    }    
    static public int[] num(int[] b){        
        for (int i = 0 ; i < b.length - 1; i++) { //确定排序次数            
            for (int j = 1; j < b.length - i; j++) { //定位排序点                
                if(b[j-1] > b[j]){ //比较,排序                    
                    //大小换位                    
                    int juan = b[j-1];                    
                    b[j-1] = b[j];                    
                    b[j] = juan;                
                }            
            }         
        }        
        return b; //返回结果    
    }
}

稀释数组

//稀疏数组

import static java.lang.System.out;

//主函数
public class Xis {
    public static void main(String[] args) {
        int[][] num = num();//得到原数组
        int[][] xishu = quzhi(num);
        out.println("======================================");
        //输出稀疏数组
        for (int i = 0; i < fuhzi(num, xishu).length; i++) {
            for (int j = 0; j < fuhzi(num, xishu)[0].length; j++) {
                out.print(fuhzi(num, xishu)[i][j] + "\t");
            }
            out.println();
        }
        out.println("++++++++++++++++++++++++++++++++++++++++");
        //稀疏数组还原
        int[][] huanyuan = huanyuan(xishu);
        for (int[] ints : huanyuan) {
            for (int j1 = 0; j1 < huanyuan[0].length; j1++) {
                out.print(ints[j1] + "\t");
            }
            out.println();
        }
    }
    //定义原数组
    public static int[][] num() { 
        int[][] num = new int[11][11];
        num[3][4] = 1;
        num[2][2] = 2;
        for (int[] ints : num) {
            for (int j = 0; j < num[0].length; j++) {
                out.print(ints[j] + "\t");
            }
            out.println();
        }
        return num;
    }
    //得到稀疏数组头
    public static int[][] quzhi(int[][] num) { 
        int shu = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (num[i][j] != 0) {
                    shu++;

                }
            }
        }
        int[][] xishu = new int[shu + 1][3];
        xishu[0][0] = num.length;
        xishu[0][1] = num[0].length;
        xishu[0][2] = shu;
        return xishu;
    }
    //原数组压缩为稀疏数组
    public static int[][] fuhzi(int[][] num, int[][] xishu) {
        int k = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (num[i][j] != 0) {
                    k++;
                    xishu[k][0] = i + 1;
                    xishu[k][1] = j + 1;
                    xishu[k][2] = num[i][j];
                }
            }
        }
        return xishu;
    }
    //稀疏数组还原
    public static int[][] huanyuan(int[][] xishu) {
        int[][] shu = new int[xishu[0][0]][xishu[0][1]];
        int i = 1;
        while (i <= xishu[0][2]) {
            shu[xishu[i][0] - 1][xishu[i][1] - 1] = xishu[i][2];
            i++;
        }
        return shu;
    }
}

结果

image-20210710220703375

System.arraycopy方法

方法原型定义为:

public static native void arraycopy(Object src,  int  srcPos, Object dest, int destPos,  int length);  

含义是复制指定源数组src到目标数组dest中。

复制从srcsrcPos索引开始,复制的个数是length,复制到dest的索引从destPos开始。

下面是一个样例:

int[] array1 = {1 ,2, 3};
int[] array2 = {4, 5, 6};
int[] array3 = new int[array1.length + array2.length];
System.arraycopy(array1, 0, array3, 0, array1.length);
//将array1复制进array3,此时array3为{1, 2, 3}
System.arraycopy(array2, 0, array3, array1.length, array2.length);
//接着array3的尾部将array2复制进array3,此时array3为{1, 2, 3, 4, 5, 6}

面向对象

以类的方式组织代码,以对象的方式封装数据。

image-20210711104734262

调用

静态

静态对象可全局直接调用

public class Demo01 {
    public static void main(String[] args) {
        System.out.println(sys());
    }

    public static String sys() {
        return "这是静态调用";
    }
}

动态

静态方法调用动态对象需要先实例化类,这个类可以是包含此对象的类本身

public class Demo01 {
    public static void main(String[] args) {
        //静态
        System.out.println(sys());
        //动态
        Demo01 demo01 = new Demo01();
        System.out.println(demo01.doc());
    }

    public static String sys() {
        return "这是静态调用";
    }
    
    public String doc(){
        return "这是动态调用";
    }
}

同一类中,动态方法调用动态对象直接调用

public class Demo01 {
    public static void main(String[] args) {
        System.out.println(sys());

        Demo01 demo01 = new Demo01();
        System.out.println(demo01.doc());
        System.out.println(demo01.doca());
    }

    public static String sys() {
        return "这是静态调用";
    }

    public String doc(){
        return "这是静态方法调用动态对象";
    }
    
    //动态调用动态
    public String doca(){
        return docb();
    }
    public String docb(){
        return "这是动态方法调用动态对象";
    }
}

image-20210711112048470

实例变量调用

同一类中调用实例对象,用this指向本身

public class Demo02 {
    String a = "这是一个实例对象";
    public String String(){
        String b = this.a;
        return b;
    }
}

image-20210711115512993

构造器

即使一个类什么都不写,也会存在一个方法,这个方法与类同名,称为构造器

  • new一个对象,本质是调用构造器

  • 一但定义有参构造,就一定要显示无参构造(无参构造默认不显示)

  • 必须和类名称相同

  • 不能有返回值,包括void

构造器实例化初始值

public class Demo03 {
    int a;

    public Demo03() {
        this.a  = 1;
    }
}

有参构造

//构造器
public class Demo03 {
    int a;

    public Demo03(){} //有参构造必须显示无参

    public Demo03(int a) {
        this.a = 1;
    }
}
//main调用输出
public class Main {
    public static void main(String[] args) {
        Demo03 demo03 = new Demo03(2);
        System.out.println(demo03.a);
    }
}

image-20210711142722986

对象内存分析

image-20210711161713587

image-20210711163816749

对象:对象是类的一个实例(对象不是找个女朋友),有状态和行为。

img

抽象

封装

封装的优点

image-20210711165329078

这里统一接口,是因为默认获取值使用getName(),修改(设置)值使用setName(),这样就达成了接口的统一

快捷键:ALT+INS

public class 封装 {
    //属性私有化
    private String name; 
    private String sex;
    private int age;
    
    //提供接口,获取数据为get,修改为set
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age; //this用于调用当前类中的属性
    }
}

public class Main {
    public static void main(String[] args) {
        封装 fenzhuang = new 封装();
        fenzhuang.setAge(12); //外部传值修改
        fenzhuang.setName("Atmujie");
        out.println(fenzhuang.getAge()); //获取类中的属性
        out.println(fenzhuang.getName());
    }
}

image-20210717100658600

重载

但一个方法需要处理多个不同类型的数据时,要用到重载

    private Scanner(Readable source, Pattern pattern) {
        assert source != null : "source should not be null";
        assert pattern != null : "pattern should not be null";
        this.source = source;
        delimPattern = pattern;
        buf = CharBuffer.allocate(BUFFER_SIZE);
        buf.limit(0);
        matcher = delimPattern.matcher(buf);
        matcher.useTransparentBounds(true);
        matcher.useAnchoringBounds(false);
        useLocale(Locale.getDefault(Locale.Category.FORMAT));
    }

    /**
     * Constructs a new {@code Scanner} that produces values scanned
     * from the specified source.
     *
     * @param  source A character source implementing the {@link Readable}
     *         interface
     */
    public Scanner(Readable source) {
        this(Objects.requireNonNull(source, "source"), WHITESPACE_PATTERN);
    }

    /**
     * Constructs a new {@code Scanner} that produces values scanned
     * from the specified input stream. Bytes from the stream are converted
     * into characters using the underlying platform's
     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
     *
     * @param  source An input stream to be scanned
     */
    public Scanner(InputStream source) {
        this(new InputStreamReader(source), WHITESPACE_PATTERN);
    }

这就是典型的重载,简单说就是方法名相同,形参类型不同是java允许的

继承

使用extends继承父类,子类/派生类继承父类的所有方法

private 属性不会被继承

final 修饰的类不能继承

所有类默认继承Object类

java只有单继承,没有多继承

  • 修饰符

    public 公共的

    private 私有的

    protected 受保护的

    default 默认 (可不写)

super

正如访问类本身的属性/方法需要使用this.属性名/方法名,在继承父类之后,子类调用父类的属性/方法需要使用super.属性名/方法名

public class 封装 {
    private String name;
    private int age;
    protected String sex = "女";
    
    public void print(){
        System.out.println("这是父类的方法");
    }
}
package oop;

public class 继承 extends 封装{
    private String sex = "男";

    public void print(){
        System.out.println("这是子类的方法");
    }

    public void sys(String sex) {
        System.out.println(sex); //这里调用的是传入的实际参数
        System.out.println(this.sex); //这里调用继承类本身的属性
        System.out.println(super.sex); //这里调用父类的属性
        print(); //直接调用
        this.print(); //这里调用继承了本身的方法
        super.print(); //这里调用父类的方法
    }
}

public class Main {
    public static void main(String[] args) {
        继承 jc = new 继承();
        jc.sys("人妖");
    }
}

image-20210717163709272

构造方法的调用

构造方法,可直接用this()super()调用,但要写在无参构造中,不写亦可,继承时会自动调用

image-20210717163853331

package oop;

public class 封装 {
    public 封装() {
        System.out.println("这是父类构造器");
    }
}

package oop;

public class 继承 extends 封装{
    public 继承() {
        super(); //调用父类构造器
    }
}

重写

重写是方法的重写,与属性无关

image-20210717165155335

父类的引用可以指向子类

注:静态方法和私有方法没有重写

方法的调用只和类型有关

image-20210717165549899

非静态方法子类重写了父类的方法

image-20210717172437056

多态

父类的引用可以指向子类

对象的实际类型是确定的,但指向的类型是不确定的

父类指向子类

  • 可以调用父类方法
  • 不能调用子类独有的方法
  • 子类重写方法,调用重写后的方法

简单来说:父类型调用子类方法,是在调用子类继承并重写后的方法

image-20210717174408823

instanceof

image-20210717175619338

instanceof用于判断两个类是否有关(继承)

类型转化

类的类型转化同变量的转化

高–>低:强制转化

低–>高:自动转化

public class 继承 extends 封装{
    private String sex = "男";
    public String abcd = "110吗,这有程序员想当黑客";
}
//父类封装是高,子类继承是低
public static void main(String[] args) {
    封装 fz = new 继承(); //子类继承转化为父类封装,自动转化,也称为多态
    System.out.println(((继承)fz).abcd);//父类要调用子类独有的属性,要强制转化
}

子类转化父类,会丢失自己独有的方法

静态方法static

static无法重写,被动态调用的直接原因是:

static和类一起加载,优先级很高,它加载时其他属性方法都没有被加载,所以无法直接调用

java执行顺序

静态代码块 –> 匿名代码块 –> 构造函数 –> 方法 【静态和类一同加载】

静态代码块整个程序运行中只执行一次

package oop;

public class 测试 {
    public 测试() {
        System.out.println("构造方法");
    }

    {
        System.out.println("匿名代码块");
    }

    static {
        System.out.println("静态代码块");
    }
}

public class Main {
    public static void main(String[] args) {
        测试 cs = new 测试();
    }
}

image-20210717203353142

抽象类

abstract

image-20210717204055895

抽象类的所有方法都要由子类去实现,不能new

一但有抽象方法,类必须声明为抽象类

image-20210717211217513

  1. 抽象类中的非抽象方法不用重写,其他必须重写,接口的方法必须重写;
  2. 接口和抽象类中只有方法名,没有定义的,如果你不定义 也就是空方法,接口就是为了弥补java不能多重继承,接口针对的是对象而不是实现。实现的部分可以交由对象去实现。

接口 interface

image-20210717211608190

实现接口的类规范命名为nameImpl

接口使用implement调用

image-20210717212749051

image-20210717212958626

image-20210717213208124

内部类

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类

成员内部类

image-20210717214102398

内部类最大的好处就是可以访问外部类的私有方法和属性

image-20210717214357851

静态内部类

静态内部类就是给成员内部类加上静态属性

局部内部类

image-20210717214615745

写在方法中的类是局部内部类

匿名内部类

image-20210717215021828

实例化时不给实例对象起名,叫匿名内部类

异常处理

image-20210718095606659

异常关键字

try、catch、finally

  • try

    监控包裹的代码块,捕获此代码块中出现的异常

  • catch

    定义捕获的异常类型,设置解决方案

    语句:catch(异常类型 自定义别名){解决方案}

    catch可以设置多个

  • finally

    对异常的善后工作,即使检测的代码块没有异常,finally还是会被执行

try,catch,finally都是对异常的检测以及抛出,往往处理无法预料的异常

public class 异常 {
    public void yich(int a,int b){
        try {
            System.out.println(a/b);
        } catch (Exception e) {
            System.out.println("异常");
        } finally {
            System.out.println("finally");
        }
    }
}

public class Main {
    public String a = "1";

    public static void main(String[] args) {
        异常 yc = new 异常();
        yc.yich(10,0);
    }
}

image-20210718101946951

throw throws

不同于try、catch、finally是在发生异常时接收,thorw和thorws用于主动抛出异常

即我们知道10/0是错误的,try会运行,发现是错误才抛出,thorwthrows是我们告诉了程序,程序遇到10/0便会直接抛出异常

  • throw

    用于主动抛出异常

  • throws

    异常在方法中无法处理,用throws将异常向上抛出,让更高级处理

这两个关键字都用在方法中

public class 异常 {
    public void thro1 (int a,int b) throws ArithmeticException{ 
        //throws遇到异常抛出指定的异常,但本身不做处理,而是抛出给上一级处理,一般和throw一起使用
        System.out.println(a / b);
    }
    
    public void thro(int a, int b) {
        if (b == 1) throw new ArithmeticException();  //throw符合条件直接抛出new的异常
    }
}
public class Main {
    public static void main(String[] args) {
        异常 yc = new 异常();
        yc.thro1(10,3);
        yc.thro(10,1);
    }
}
public class 异常 {
    public void thro(int a, int b){
        try {
            throw new ArithmeticException();
        }
        catch (Exception e){
            System.out.println("异常。。。重试。。。");
        }
    }
}

image-20210718204858832

自定义异常

public class 自定义异常 extends Exception{  //继承异常类的子类可作为自定义异常
    private int  detail;
    public 自定义异常(int a){
        this.detail = a;
    }

    @Override
    public String toString() {
        return "自定义异常{" +
                "detail=" + detail +
                '}';
    }
}

public class 异常 {
    static void test(int a) throws 自定义异常 {
        if (a > 10) throw new 自定义异常(a);
        else System.out.println("a < 10");
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            异常 yc = new 异常();
            yc.test(1);
            yc.test(11);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

l


文章作者: Atmujie
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Atmujie !
评论
  目录