JAVA基础知识点

4 篇文章 0 订阅

注:本文参考自菜鸟教程,部分图片也来自菜鸟教程
菜鸟教程:https://www.runoob.com/java/java-tutorial.html

一、Java基础

1,JDK、JRE和JVM之间的关系

  • JDK(Java Development Kit):Java开发工具包,jdk是整个Java开发的核心,它集成了jre和一些好用的小工具(javac.exe,java.exe,jar.exe等)。
  • JRE(Java Runtime Environment):Java运行时环境。主要包含两个部分,jvm的标准实现和java的一些基本类库。它相对于jvm来说,多出来的是一部分的java类库。
  • JVM(Java Virtual Machine):Java虚拟机。只认识xxx.class类型文件,它能够将class文件中的字节码指令进行识别并调用操作系统向上的API完成动作。所以说jvm是Java能够跨平台的核心。

三者关系可以理解为嵌套关系:JDK>JRE>JVM

2,== 和 equals() 的区别是什么?

什么是==

== 比较运算符,如果进行比较的两个操作数都是数值类型,即使他们的数据类型不相同,只要他们的值相等,也都将返回true.如果两个操作数都是引用类型,那么只有当两个引用变量的类型具有父子关系时才可以比较,而且这两个引用必须指向同一个对象,才会返回true.(在这里我们可以理解成==比较的是两个变量的内存地址)

什么是equals()

equals()方法是Object类的方法,在Object类中的equals()方法体内实际上返回的就是使用==进行比较的结果.但是我们知道所有的类都继承Object,而且Object中的equals()方法没有使用final关键字修饰,那么当我们使用equal()方法进行比较的时候,我们需要关注的就是这个类有没有重写Object中的equals()方法.

区别

  1. ==是判断两个变量或实例是不是指向同一个内存空间,equals()是判断两个变量或实例所指向的内存空间的值是不是相同。
  2. ==是指对内存地址进行比较,equals()是对字符串的内容进行比较。
  3. ==是指引用是否相同,equals()是指的值是否相同。

int 和 Integer比较

 public static void main(String[] args) {
        System.out.println("-128 ~ +127 之间");
        Integer a = 5;
        int b = 5;
        Integer c = new Integer(5);
        Integer d = 5;

        System.out.println(a.equals(b));
        System.out.println(a == b);
        System.out.println(a.equals(c));
        System.out.println(a == c);
        System.out.println(a == d);

        System.out.println("--------------------------");

        System.out.println("-128 ~ +127 之外");
        a = 128;
        b = 128;
        c = new Integer(128);
        d = 128;

        System.out.println(a.equals(b));
        System.out.println(a == b);
        System.out.println(a.equals(c));
        System.out.println(a == c);
        System.out.println(a == d);
    }

结果:
在这里插入图片描述
注意:

  • 赋值方式中如果调用了new关键字,一定会在内存中给你分配一个新的地址
  • 给Integer类型赋值的时候,如果没有调用new关键字,并且值在-128与+127之间,包括-128和+127,那么指向的都是同一个内存位置.
  • Integer类中重写了equals()方法,使用equals()方法进行比较的时候,实际上比较的内存中最终指向的值的内存位置,不是直接比较变量的内存位置.

3,final 在 java 中有什么作用

final是Java的关键字,可用于三个地方(修饰类,修饰方法和修饰变量)。
特征:凡是引用final关键字的地方皆不可修改

  1. 修饰类:表示该类不能被继承。
  2. 修饰方法:表示方法不能被重写。
  3. 修饰变量:表示变量只能一次赋值以后值不能被修改(可以理解为常量)

可参考:https://blog.csdn.net/qq_24309787/article/details/100942044

4,&与&&区别

  1. &与&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算运算结果才为true,否则,只要有一方为false,则结果也为false。
  2. &&还具有短路功能,即如果第一个表达式为false,则不再计算第二个表达式。
  3. &还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作。

简单的说:
&是位运算,返回结果是int型。
&&是逻辑运算,返回结果是boolean型。
&不管前面的条件是否正确,后面都执行。
&&前面条件正确时,才执行后面,不正确时,就不执行,就效率而言,这个更好。

扩展:java中&和&&的区别,java中||和|符号的区别
(&,|)它们是逻辑操作,(&&,||)它们是条件操作。
&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑运算与(and).
|是按位或运算符 ,表示按位或运算,||是逻辑或算符,表示逻辑或运算。
条件操作只能操作布尔型的,而逻辑操作不仅可以操作布尔型,而且可以操作数值型的。
不同点:
对于A&B,不管a是否为假,仍然要判断B。
对于A|B,不管a是否为真,仍然要判断B。
而对于A&&B,A||B在以上情况就不会去判断B了。

5,两个对象的hashCode()相同,则equals()是否也一定true

不一定。
反过来equals为true时,hashCode一定相同。
类的hashCode方法和equals方法都可以重写,返回值完全在于自己定义。
hashCode() 返回该对象的哈希码值;equals() 返回两个对象是否相等。

关于 hashCode 和 equals 方法是有一些 常规协定 :

1、两个对象用 equals() 比较返回true,那么两个对象的 hashCode() 方法必须返回相同的结果。
2、两个对象用 equals() 比较返回false,不要求 hashCode() 方法也一定返回不同的值,但是最好返回不同值,以提搞哈希表性能。
3、重写 equals() 方法,必须重写 hashCode() 方法,以保证 equals 方法相等时两个对象 hashcode 返回相同的值。

6,Java中操作字符串都有哪些类,之间有什么区别

String,StringBuffer,StringBuilder

  • String:final修饰,String类的方法都是返回new String。即对String对象的任何改变都不影响原对象,对字符串的修改操作都会生成新的对象,不可被继承。
  • StringBuffer:对字符串的操作方法都加了synchronized,保证线程安全。
  • StringBuilder:不保存线程安全,在方法体内需要进行字符串的修改操作,可以new StringBuilder对象,调用StringBuilder对象的append,replace,delete等方法修改字符串。

7,传引用和传值的区别

  • 当对象通过传值调用时,传递的是这个对象的一个拷贝。因此,即使函数修改这个对象,也不会影响原对象的值。
  • 当对象通过传引用调用时,对象本身没有被传递,而传递的是对象的一个引用。因此,外部函数对这个对象的修改,也会反映到任何出现这个对象的地方。

什么情况下发生传值,什么情况下发生传引用

  • 如果是基本数据类型和String,则实参不会改变,因为传的是值。
  • 但如果传的是对象集合或者数组,就会改变,因为传的是引用。

8,自动装箱和拆箱

  • 装箱:将基本类型用他们对应的引用类型包装起来
  • 拆箱:将包装类型转换为基本数据类型
  • 自动装箱表示对于byte、short、int、long、float、double、boolean、char,可以自动将其转换成对应的Byte、Short、Integer、Long、Float、Double、Boolean、Char对象。
  • 自动拆箱则是自动装箱的反过程。

9,类的实例化顺序

父类静态成员和静态代码块->子类静态成员和静态代码块->父类非静态成员和非静态代码块->父类构造方法->子类非静态成员和非静态代码块->子类构造方法

10,Java的类加载器有哪几种,分别是什么

可参考:http://gityuan.com/2016/01/24/java-classloader/

启动类加载器,扩展类加载器,应用程序类加载器,用户自定义类加载器。

ClassLoader即常说的类加载器,其功能是用于从Class文件加载所需的类,主要场景用于热部署、代码热替换等场景。系统提供3种的类加载器:Bootstrap ClassLoader、Extension ClassLoader、Application ClassLoader

  1. Bootstrap ClassLoader
    启动类加载器,一般有C++实现,是虚拟机的一部分。该类加载器主要职责是将JAVA_HOME路径下的\lib目录中能被虚拟机是被的类库(比如rt.jar)加载到虚拟机内存中。Java程序无法直接引用该类加载器。
  2. Extension ClassLoader
    扩展类加载器,由Java实现,独立于虚拟机的外部。该类加载器主要职责将JAVA_HOME路径下的\lib\ext目录中的所有类库,开发者可直接使用扩展类加载器。 该加载器是由sun.misc.Launcher$ExtClassLoader实现。
  3. Application ClassLoader
    应用程序类加载器,该加载器是由sun.misc.Launcher$AppClassLoader实现,该类加载器负责加载用户类路径上所指定的类库。开发者可通过ClassLoader.getSystemClassLoader()方法直接获取,故又称为系统类加载器。当应用程序没有自定义类加载器时,默认采用该类加载器。
  4. CustomClassLoader
    自定义类加载器,通过继承ClassLoader类实现,主要重写findClass方法。

扩展

类加载器的层级查找顺序依次为:启动类加载器,扩展类加载器,系统类加载器。系统类加载器是默认的应用程序类加载器。

在这里插入图片描述

11,双亲委派机制

当某个特定的类加载器它在接到需要加载类的请求时,这个类会首先查看自己已加载完的类中是否包含这个类,如果有就返回,没有的话就会把加载的任务交给父类加载器加载,以此递归,父类加载器如果可以完成类加载任务,就返回它,当父类加载器无法完成这个加载任务时,才会不得已自己去加载。这种机制就叫做双亲委派机制。

12,switch语句能否作用于byte上,能否作用于long上,能否作用于String上

  • switch可作用于char byte short int。
  • switch可作用于char byte short int对应的包装类。
  • switch不可作用于long double float boolean,包括他们的包装类 Long/Double。
  • switch中可以是字符串类型,String(jdk1.7之后才可以作用在String上)。
  • switch中可以是枚举类型。

13,try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行。在return前还是后

在return前执行

  • try中的return语句调用的函数先于finally中调用的函数执行,也就是说return语句先执行,finally语句后执行。
  • return并不是让函数马上返回,而是return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回。

14,Java Number & Math 类

可参考:https://www.runoob.com/java/java-number.html

Math 的 floor,round 和 ceil 方法实例比较
在这里插入图片描述

15,Java权限修饰符对应访问权限大小

在这里插入图片描述
扩展:构造方法的权限修饰符与类一致

16,final、finalize 和 finally 的不同之处

  • final 是一个修饰符,可以修饰变量、方法和类。如果 final 修饰变量,意味着该变量的值在初始化后不能被改变。
  • finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的,但是什么时候调用 finalize 没有保证。
  • finally 是一个关键字,与 try 和 catch 一起用于异常的处理。finally 块一定会被执行,无论在 try 块中是否有发生异常。

二、Java面向对象

1,Overload(重载)和Override(重写)区别

  • 方法的重载和重写都是实现多态的方式。
  • 重载实现的是编译时的多态性,重写实现的是运行时的多态性。
  • 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
    每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
    最常用的地方就是构造器的重载。
  • 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。

扩展:多态是同一个行为具有多个不同表现形式或形态的能力。

方法重写规则

  1. 参数列表与被重写方法的参数列表必须完全相同。
  2. 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
  3. 访问权限不能比父类中被重写的方法访问权限更底(public>protected>default>private)。
  4. 父类的成员方法只能被它的子类重写。
  5. 声明为final的方法不能被重写。
  6. 声明为static的方法不能被重写,但是能够被再次声明。
  7. 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
  8. 子类个父类不在同一个包中,那么子类只能重写父类声明为public和protected的非final方法。
  9. 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  10. 构造方法不能被重写。
  11. 如果不能继承一个类,则不能重写改方法。

扩展:当需要在子类中调用父类的被重写方法时,要使用 super 关键字。

class Animal{
   public void move(){
      System.out.println("动物可以移动");
   }
}
 
class Dog extends Animal{
   public void move(){
      super.move(); // 应用super类的方法
      System.out.println("狗可以跑和走");
   }
}
 
public class TestDog{
   public static void main(String args[]){
 
      Animal b = new Dog(); // Dog 对象
      b.move(); //执行 Dog类的方法
 
   }
}

输出结果:
动物可以移动
狗可以跑和走

方法的重载规则

  1. 被重载的方法必须改变参数列表(参数个数或类型不一样)。
  2. 被重载的方法可以改变返回类型。
  3. 被重载的方法可以改变访问修饰符。
  4. 被重载的方法可以声明新的或更广的检查异常。
  5. 方法能够在同一个类中或在一个子类中被重载。
  6. 无法以返回值类型作为重载函数的区分标准。

重写与重载之间的区别

区别点重载重写
参数列表必须修改不能修改
返回类型可以修改不能修改
异常可以修改可以减少或删除,但不能抛出新的或者更广的异常
访问可以修改不能做更严格的限制(可以降低限制public>protected>default>private)

总结
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式

  1. 方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
  2. 方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
  3. 方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
    在这里插入图片描述

2,继承

继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力

类的继承格式
通过 extends 关键字实现继承关系

class 父类 {
}
 
class 子类 extends 父类 {
}

继承的特性

  • 子类拥有父类非private的属性、方法。
  • 子类可以拥有自己的属性和方法、即子类可以对父类进行扩展。
  • java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

继承类型
Java 不支持多继承,但支持多重继承。
在这里插入图片描述
扩展:
super 与 this 关键字
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。

class Animal {
  void eat() {
    System.out.println("11111");
  }
}
 
class Dog extends Animal {
  void eat() {
    System.out.println("22222");
  }
  void eatTest() {
    this.eat();   // this 调用自己的方法
    super.eat();  // super 调用父类方法
  }
}
 
public class Test {
  public static void main(String[] args) {
    Animal a = new Animal();
    a.eat();
    Dog d = new Dog();
    d.eatTest();
  }
}

输出结果:
11111
22222
11111
final关键字
final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:

声明类:

final class 类名 {//类体}

声明方法:

修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}

注:实例变量也可以被定义为 final,被定义为 final 的变量不能被修改。被声明为 final 类的方法自动地声明为 final,但是实例变量并不是 final。
构造器
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。

如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

3,多态

  • 多态是同一个行为具有多个不同表现形式或形态的能力。
  • 多态就是同一个接口,使用不同的实例而执行不同的操作。
  • 多态性是对象多种表现形式的体现。

多态的优点

  1. 消除类型之间的耦合关系

  2. 可替换性:多态对已存在的代码具有可替换性。

  3. 可扩充性:多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际 上新加子类更容易获得多态功能。

  4. 接口性:多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。

  5. 灵活性:它在应用中体现了灵活多样的操作,提高了使用效率。

  6. 简化性:多态简化了对应用软件的代码编写和修改过程。

实现多态的两种形式

  • 使用父类作为方法形参实现多态
public void play(Pet p){}
  • 使用父类作为方法返回值实现多态
 public Pet getPet(int type){}

多态存在的三个必要条件

  1. 编写具有继承关系的父类,子类。
  2. 子类重写父类方法。
  3. 使用父类的引用指向子类对象。

4,封装

将类的某些信息隐藏在类的内部,不允许外部程序直接访问,并通过该类提供的方法来实现对隐藏信息的操作和访问。(简单的说就是隐藏对象的信息,留出访问的接口)。

封装的优点

  1. 良好的封装能够减少耦合。
  2. 类内部的结构可以自由修改。
  3. 可以对成员变量进行更精确的控制。
  4. 隐藏信息,实现细节。

5,抽象类

用abstract 关键字来修饰一个类时,这个类叫作抽象类。抽象类是它的所有子类的公共属性的集合,是包含一个或多个抽象方法的类。抽象类可以看作是对类的进一步抽象。在面向对象领域,抽象类主要用来进行类型隐藏。

抽象类格式

public abstract class ClassName {}

抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。抽象方法格式

public abstract class Employee
{
   public abstract double computePay();
}
  • 抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。
  • 包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。

抽象类和普通类的区别

  1. 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
  2. 抽象类不能用来创建对象。
  3. 如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类

6,接口

接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

  • 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
  • 接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口的声明语法格式

public  interface 接口名称 [extends 其他的接口名] {
        // 声明变量(任何类型 final, static 字段)
        // 抽象方法
}

接口的实现

  • 当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

  • 类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
    语法格式

public class 类名 implements 接口名称1,接口名称2...{
    //方法
}

接口特性

  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
  • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
  • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

接口与类的区别

  1. 接口不能用于实例化对象。
  2. 接口没有构造方法。
  3. 接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
  4. 接口不能包含成员变量,除了 static 和 final 变量。
  5. 接口不是被类继承了,而是要被类实现。
  6. 接口支持多继承。

扩展
接口和抽象类的区别

  1. 子类只能继承一个抽象类,但可以实现任意多个接口。
  2. 接口中的方法都是抽象方法,抽象类可以有非抽象方法。
  3. 抽象类中的成员变量可以是各种类型,接口中的成员变量只能是静态常量。
  4. 抽象类中可以有静态方法和静态代码块,而接口中不行。
  5. 接口没有构造方法, 抽象类里可以有构造方法。

什么时候使用接口?什么时候使用抽象类?
使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。
抽象类适合用来定义某个领域的固有属性,也就是本质,接口适合用来定义某个领域的扩展功能。

一、什么时候使用抽象类?

  1. 当2个或多个类中有重复部分的时候,我们可以抽象出来一个基类,如果希望这个基类不能被实例化,就可以把这个基类设计成抽象类。
  2. 当需要为一些类提供公共的实现代码时,应优先考虑抽象类 。因为抽象类中的非抽象方法可以被子类继承下来,使实现功能的代码更简单。
  3. 抽象类只能是单继承的,不能多继承。

二、什么时候使用接口?

  • 当注重代码的扩展性跟可维护性时,应当优先采用接口。
    ①接口与实现它的类之间可以不存在任何层次关系,接口可以实现毫不相关类的相同行为,比抽象类的使用更加方便灵活;
    ②接口只关心对象之间的交互的方法,而不关心对象所对应的具体类。接口是程序之间的一个协议,比抽象类的使用更安全、清晰。一般使用接口的情况更多。

7,Java面向对象的三大特征

封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

继承:继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

  • 子类拥有父类非private的属性和方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。

多态:是同一个行为具有多个不同表现形式或形态的能力。
实现多态:
1》编写具有继承关系的父类,子类 。
2》子类重写父类方法。
3》使用父类的引用指向子类对象。
实现多态的两种形式:
1》使用父类作为方法形参实现多态 。
2》使用父类作为方法返回值实现多态。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值