2021-10-14

继承

继承——尽量少使用继承,应该采用接口进行替换

当不知道采用继承还是接口的时候,应该优先考虑采用接口。

继承用来表示类和类之间的关系

public class Father {
    // 很多方法和属性
}

public class Child extendsFather {
    //
}

继承可以继承哪些内容?

可以被继承的内容只有属性和方法。构造块和构造器是无法继承的。

虽然构造块和构造器是无法继承的,但是会在创建子类对象的时候被自动调用。

当父子类中包含静态或非静态的构造块以及构造器的时候

1.static内容一定是先执行完毕的(也是先父后子)

2.父类的非静态内容一定优先于子类执行完毕

父类

public class Father {

    public Father() {
        System.out.println("父类的构造器");
    }

    {
        System.out.println("父类的构造块");
    }

    static {
        System.out.println("父类中的静态块");
    }

}

子类

public class Child extends Father {

    public Child () {
        System.out.println("子类的构造器");
    }

    {
        System.out.println("子类的构造块");
    }

    static {
        System.out.println("子类中的静态块");
    }

    public static void main(Sring[] args) {
        // 不创建对象时,父类和子类的构造块和构造器都不会执行
        Child child = new Child();
    }
}

super关键字(注意对比this)

1. 调用父类的属性和方法super.属性 super.方法()

2. 调用父类构造器——所有类的构造器中都有一个隐含的super();

super() 调用父类构造器必须出现在构造器的第一行,这个要求和this()一样

那就意味着 super() 和 this() 不能同时出现

考点:注意看父类是否有不带参数的构造器

public class Child extends Father { 
    public Child() {
        System.out.println("子类的构造器");
    }
    public Child(int i) {
        super();
        // this(); 不能同时书写this()和super()
       System.out.println("子类的带参数构造器");
    }
    void g(){
       super.f();
       this.f();
    }
    public static void main(String[] args) {
      
    }

覆盖(重写)

重写和重载的思路类似。因为一个类中不允许有相同的方法名存在,但是重载和重写是两个例外。

1.方法签名必须完全一样(方法签名 = 方法名 + 参数列表)

2.返回类型必须相同或者更窄(子类)

3. 修饰符必须相同或更宽 (更窄private < defalut < protected < public 更宽)

public class Father {
    protected Father f() {
        return null;
    }
}
public class Child extends Father {
    @Override // 这个注解的作用只是为了帮助校验一下这个方法f是不是一个正确的重写
    public Child f() {
        return null;
    }
}

重写必须有父类和子类

重载可以只是单一的类,也可以出现在父子类中

// 第一种
    protected Father f() {
        return null;
    }

// 第二种
    void f(double d) {

    }

// 第三种
    public class Child extends Father{
        public Child f(int i){ //重载
            return null;
        }
    }

以上父子类中的三个方法f是互相重载的。

抽象类:对于现实世界中的抽象概念,可以使用抽象类来表示。比如形状。

抽象类的用处实际上就是用来作为父类使用。

public abstract class A {

} 

抽象类不能创建对象

抽象类可以有构造器

public abstract class A { 
    public A() { 
    
}

    public static void main(String[] args) {
        A a = new A(); //错误,抽象类不能创建对象
    }
} 

既然抽象类不能创建对象,那么要构造器有什么用处?

抽象类虽然不能创建对象,但是可以被继承。当它有了子类后,子类的构造器一定会调用父类的构造器。 所以抽象类的构造器是用于子类创建对象是被优先调用的。

public abstract class A { 
    public A() { 
        System.out.println("抽象类A的构造器"); 
    } 
} 

public class B extends A{ 
    public B() { 
        System.out.println("子类B的构造器"); 
    }

    public static void main(String[] args) {
        B b = new B();
    }
}

抽象方法

用abstract修饰的方法就是抽象方法。抽象方法不能有方法体。

如果一个类中包含抽象方法,那么这个类就必须被标记为抽象的。

但是要注意,一个抽象类中可以没有抽象方法。

抽象方法怎么用?

抽象方法就是用来被实现的,谁继承了包含抽象方法的类,就必须实现抽象方法或者将自己变为抽象类。

public class A { 
    public void f() { 
    } 
}

public abstract class B extends A{ 
    @Override 
    public abstract void f(); 
    //可以把父类中的方法在子类中覆盖为抽象方法 
}

内部类: 面试经常问有哪些内部类,它们的特点是什么。

1.嵌套内部类

public class Outer { //类可以是defalut和public的 
    class inner { //内部类可以是private,defalut,protected,public的任意一种 
    } 
}

2.静态内部类

public class Outer { 
    static class inner { 
    } 
}

3.局部内部类: 出现在方法中的类

public class Outer { 
    public void f() { 
        class C{

        }
    }
}

4.匿名内部类

通常是new 类名/接口名{

}

new后面的类名/接口名中一定包含抽象方法,在匿名内部类中给出抽象方法的实现即可。

abstract class A { 
    abstract void f();
    abstract void g(); 
}

public class Outer { 
    public static void main(String[] args) { 
        A a = new A() { 
            @Override 
            void f() { 
                System.out.println("f"); 
            }

        @Override
        void g() {
            System.out.println("g");
        }
    };
​
    a.f();
    a.g();
}

}

异常

  1. 异常的捕获: try-catch
  2. 异常的声明:throws:声明异常和是否发生这种异常是两回事。
  3. 异常的抛出:throw

所有的异常都是对象,抛出异常实际上就是产生一个对象。

catch捕获异常,实际上可以理解为一个异常对象被当做参数传递到catch中。

       try {
            throw new IOException(); // 异常的抛出
        } catch (IOException e) { // 异常的捕获
            e.printStackTrace();
        }

 

      try {
            throw new IOException(); 
        } catch (ArrayIndexOutOfBoundsException | ArithmeticException | IOException e) { 
            //当try中可能出现多个异常,且这些异常的处理方式都是相同的情况下,可以写为上面的形式。
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("xxxx");
        }
        try (InputStream is = new FileInputStream("a")) {
            // try后面放圆括号是为了自动关闭其中的内容,而且这个关闭一定是通过调用close方法来完成
            // 哪些内容可以自动关闭? 实现了Closeable接口的内容是可以用于这种语法中的
            System.out.println(is.available());
        } catch (IOException e) {
            e.printStackTrace();
        }

I/O输入/输出

Files是一个工具类,用于处理文件、文件夹(目录)

这个工具类不涉及文件中的内容,只是负责建立、删除、判断是否存在等操作。

Linux不严格区分文件还是文件夹,一切都是文件夹

 // Path表示路径,即文件或者文件夹的路径和名字
        // 一个路径是否存在、不区分到底它是文件还是文件夹,这要取决于后续调用的方法
        Path file = Path.of("D:\\aa.txt");
        Path dir = Path.of("D:\\abc");

        if (Files.notExists(file))
            Files.createDirectory(file); // 建文件夹

        if (Files.notExists(dir))
            Files.createDirectory(dir); // 建立文件夹
        System.out.println("是否隐藏?" + Files.isHidden(file)); // 判断一个文件或者文件夹是否是隐藏的
        System.out.println("是否可执行?" + Files.isExecutable(file)); // exe才是可执行
        System.out.println("是否可被修改?" + Files.isWritable(file)); // 是否可被修改
        Files.deleteIfExists(file); // 如果文件或文件夹存在则将其删除
        Files.deleteIfExists(dir);
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值