跳到主要内容
  1. 所有文章/
  2. Java基础知识笔记汇总/

基础语法、关键字、面向对象

·📄 2493 字·🍵 5 分钟

基础语法 #

long 类型的数据一定要在数值后面加上 L,否则将作为整型解析。 #

switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上? #

Java5 以前 switch(expr)中,expr 只能是 byte、short、char、int

从 Java 5 开始,Java 中引入了枚举类型, expr 也可以是 enum 类型。

从 Java 7 开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

访问修饰符public、private、protected、以及不写(默认)时的区别? #

  • privateprotected无法用来修饰类。

image-20210219173433142.png

image-20220212180440670.png

关键字 #

final、finally、finalize的区别? #

final 用于修饰变量、方法和类。

  • final 变量:被修饰的变量不可变,不可变分为引用不可变对象不可变,final 指的是引用不可变,final 修饰的变量必须初始化,通常称被修饰的变量为常量
  • final 方法:被修饰的方法不允许任何子类重写,子类可以使用该方法。
  • final 类:被修饰的类不能被继承,所有方法不能被重写。

finally 作为异常处理的一部分,它只能在 try/catch 语句中,并且附带一个语句块表示这段语句最终一定被执行(无论是否抛出异常),经常被用在需要释放资源的情况下,System.exit (0) 可以阻断 finally 执行。

finalize 是在 java.lang.Object 里定义的方法,也就是说每一个对象都有这么个方法,这个方法在 gc 启动,该对象被回收的时候被调用

一个对象的 finalize 方法只会被调用一次,finalize 被调用不一定会立即回收该对象,所以有可能调用 finalize 后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会再次调用 finalize 了,进而产生问题,因此不推荐使用 finalize 方法。

为什么要用static关键字? #

通常来说,用new创建类的对象时,数据存储空间才被分配,方法才供外界调用。但有时我们只想为特定域分配单一存储空间,不考虑要创建多少对象或者说根本就不创建任何对象,再就是我们想在没有创建对象的情况下也想调用方法。在这两种情况下,static关键字,满足了我们的需求。

  • static方法无法被重写
  • static方法可以访问static变量,因为都是类初始化时加载
  • static方法不可以访问非static方法
  • 代码块执行顺序静态代码块——> 构造代码块 ——> 构造函数——> 普通代码块  继承中代码块执行顺序:父类静态块——>子类静态块——>父类代码块——>父类构造器——>子类代码块——>子类构造器

面向对象 #

  • 封装。封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
  • 继承。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。
  • 多态性。它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,这使得同一个属性或方法在父类及其各个子类中具有不同的含义。

Java语言是如何实现多态的? #

本质上多态分两种:

  1. 编译时多态(又称静态多态)
  2. 运行时多态(又称动态多态)

重载(overload)就是编译时多态的一个例子,编译时多态在编译时就已经确定,运行的时候调用的是确定的方法。我们通常所说的多态指的都是运行时多态,也就是编译时不确定究竟调用哪个具体方法,一直延迟到运行时才能确定。 这也是为什么有时候多态方法又被称为延迟方法的原因。

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

构造器不能被继承,因此不能被重写,但可以被重载。每一个类必须有自己的构造函数,负责构造自己这部分的构造。子类不会覆盖父类的构造函数,相反必须一开始调用父类的构造函数

image-20220212185902071.png

抽象类和接口的区别是什么? #

语法层面上的区别:

  • 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
  • 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

设计层面上的区别:

  • 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
  • 设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。

想要深入了解,可以参考这篇文章 :https://www.cnblogs.com/dolphin0520/p/3811437.html

java 创建对象有哪几种方式? #

java中提供了以下四种创建对象的方式:

  • new创建新对象
  • 通过反射机制
  • 采用clone机制
  • 通过序列化机制

前两者都需要显式地调用构造方法。对于clone机制,需要注意浅拷贝和深拷贝的区别,对于序列化机制需要明确其实现原理,在java中序列化可以通过实现Externalizable或者Serializable来实现。

package demo1;


import java.io.*;
import java.lang.reflect.InvocationTargetException;

public class Main1 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException,
            InvocationTargetException, CloneNotSupportedException, IOException, ClassNotFoundException {
        //第一种
        Demo demo=new Demo();
        System.out.println(demo);
        //第二种
        Class<Demo> demoClass=Demo.class;
        System.out.println(demoClass.newInstance());
        System.out.println(demoClass.getConstructors()[0].newInstance());
        //第三种
        Demo demoClone=(Demo)demo.clone();
        System.out.println(demoClone);
        //第四种
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("demo.ser"));
        objectOutputStream.writeObject(demo);
        objectOutputStream.close();
        ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("demo.ser"));
        Demo demoSer=(Demo)objectInputStream.readObject();
        System.out.println(demoSer);
    }
}

class Demo implements Cloneable, Serializable {
    public Demo(){
        System.out.println("Demo类被创建啦");
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

image-20220212192042574.png

什么是不可变对象?好处是什么? #

不可变对象指对象一旦被创建,状态就不能再改变,任何修改都会创建一个新的对象,如 String、Integer及其它包装类.不可变对象最大的好处是线程安全.

能否创建一个包含可变对象的不可变对象?

当然可以,比如final Person[] persons = new Persion[]{}persons是不可变对象的引用,但其数组中的Person实例却是可变的.这种情况下需要特别谨慎,不要共享可变对象的引用.这种情况下,如果数据需要变化时,就返回原对象的一个拷贝.