2024年最新JavaSE(基础篇)——面向对象(万字总结,java高级架构师面试题

笔者福利

以下是小编自己针对马上即将到来的金九银十准备的一套“面试宝典”,不管是技术还是HR的问题都有针对性的回答。

有了这个,面试踩雷?不存在的!

回馈粉丝,诚意满满!!!




本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

print();

this.print();

super.print();

} }

【调用父类中的构造器】

public class Person{

}

public class Student extends Person{

//编译通过,子类构造器中会隐式的调用父类的无参构造器

//super();

public Student(){

}

}

父类没有无参构造

public class Person{

protected String name;

public Person(String name){

this.name = name;

}

}

public class Student extends Person{

//编译报错,子类构造器中会隐式的调用父类的无参构造器,但是父类中没有无参构造器

//super();

public Student(){

}

}

【显式的调用父类的有参构造器】

public class Person{

protected String name;

public Person(String name){

this.name = name;

}

}

public class Student extends Person{

//编译通过,子类构造器中显式的调用父类的有参构造器

public Student(){

super(“tom”);

}

}

注:不管是显式还是隐式的父类的构造器,super语句一定要出现在子类构造器中第一行代码。所以this和super不可能同时使用它们调用构造器的功能,因为它们都要出现在第一行代码位置。

【super使用的注意的地方】

1.用super调用父类构造方法,必须是构造方法中的第一个语句。

2.super只能出现在子类的方法或者构造方法中。

3.super 和 this 不能够同时调用构造方法。(因为this也是在构造方法的第一个语句)。

【super 和 this 的区别】

1.代表的事物不一样:

this :代表所属方法的调用者对象。

super:代表父类对象的引用空间。

2.使用前提不一致:

this:在非继承的条件下也可以使用。

super:只能在继承的条件下才能使用。

3.调用构造方法:

this:调用本类的构造方法。

super:调用的父类的构造方法

方法的重写


方法的重写(override

1. 方法重写只存在于子类和父类(包括直接父类和间接父类)之间。在同一个类中方法只能被重载,不能被重写.

2.静态方法不能重写。

1. 父类的静态方法不能被子类重写为非静态方法 //编译出错

2. 父类的非静态方法不能被子类重写为静态方法;//编译出错

3. 子类可以定义与父类的静态方法同名的静态方法(但是这个不是覆盖)

【例子】

A类继承B类

A和B中都一个相同的静态方法test

B a = new A();

a.test();

//调用到的是B类中的静态方法test

A a = new A();

a.test();

//调用到的是A类中的静态方法test

可以看出静态方法的调用只和变量声明的类型相关

这个和非静态方法的重写之后的效果完全不同

1. 私有方法不能被子类重写,子类继承父类后,是不能直接访问父类中的私有方法的,那么就更谈不上重写了。

【例子】

public class Person{ private void run(){

}

}

//编译通过,但这不是重写,只是俩个类中分别有自己的私有方法

public class Student extends Person{

private void run(){

}

}

重写的语法

1.方法名必须相同。

2.参数列表必须相同。

3.访问控制修饰符可以被扩大,但是不能被缩小: public protected default private。

4.抛出异常类型的范围可以被缩小,但是不能被扩大。

ClassNotFoundException —> Exception

5.返回类型可以相同,也可以不同,如果不同的话,子类重写后的方法返回类型必须是父类方法返回类型的子类型。

例如:父类方法的返回类型是Person,子类重写后的返回类可以是Person也可以是Person的

子类型

为什么要重写?

子类继承父类中的方法,但是父类中的方法并不满足子类的功能需求,所以子类中要把方法进行重写。

总结:

方法重写的时候,必须存在继承关系。

方法重写的时候,方法名和形式参数 必须跟父类是一致的。

方法重写的时候,子类的权限修饰符必须要大于或者等于父类的权限修饰符。( private < protected <public,friendly < public )

方法重写的时候,子类的返回值类型必须小于或者等于父类的返回值类型。( 子类 < 父类 ) 数据类型没有明确的上下级关系

方法重写的时候,子类的异常类型要小于或者等于父类的异常类型。


多态

==

认识多态


多态是OOP(面向对象)中一个重要的特性,主要是用来实现动态联编的,换句话说就是程序的最终状态就有在执行过程中才被决定而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性和扩展性。

相同类域的不同对象,调用相同的方法,执行结果是不同的:

1.一个对象的实际类型是确定的

例如:

Person s1 = new Student;

//和

Student s2 = new Student;

//是不相同的

2.可以指向对象的引用的类型有很多

一个对象的实现类型虽然是确定的,但是这个对象所属的类型可能有很多种。

例如:Student继承了Person类

Studnet s1 = new Student;

Person s2 = new Student;

Object s3 = new Student;

因为Person和Object都是Student的父类。

注:一个对象的实际类型是确定,但是可以指向这个对象的引用的类型,却是可以是这对象实际类型的任意父类型

1.一个父类引用可以指向它的任何一个子类对象

例如:

Object o = new AnyClass();

Person p = null;

p = new Student();

p = new Teacher();

p = new Person();

2.多态中的方法调用

例如:

public class Person{

public void run(){

}

}

public class Student extends Person{

}

3.调用到的run方法,是Student从Person继承过来的run方法

main:

Person p = new Student();

p.run();

例如:

public class Person{

public void run(){

}

}

public class Student extends Person{

public void run(){

//重写run方法

}

}

//调用到的run方法,是Student中重写的run方法

main:

Person p = new Student();

p.run();

注:子类继承父类,调用a方法,如果a方法在子类中没有重写,那么就是调用的是子类继承父类的a方法, 如果重写了,那么调用的就是重写之后的方法。

子类中独有方法的调用

public class Person{

public void run(){

}

}

public class Student extends Person{

public void test(){

}

}

main:

Person p = new Student();

//调用到继承的run方法 p.run();

//编译报错,因为编译器检查变量p的类型是Person,但是在Person类中并没有发现test方法,所以编 译报错.

p.test();

注:一个变量x,调用一个方法test,编译器是否能让其编译通过,主要是看声明变量x的类型中有没有定义test方法,如果有则编译通过,如果没有则编译报错.而不是看x所指向的对象中有没有test方法.

原理:编译看左边,运行不一定看右边。

编译看左边的意思: java 编译器在编译的时候会检测引用类型中含有指定的成员,如果没有就会报错。子类的成员是特有的,父类的没有的,所以他是找不到的。

子类和父类引用指向对象的区别

Student s = new Student();

Person p = new Student();

Object o = new Student();

变量s能调用的方法是Student中有的方法(包括继承过来的),变量p能调用的方法是Person中有的方法(包括继承过来的)。

但是变量p是父类型的,p不仅可以指向Student对象,还可以指向Teacher类型对象等,但是变量s只能指Studnet类型对象,及Student子类型对象。变量p能指向对象的范围是比变量s大的。

Object类型的变量o,能指向所有对象,它的范围最大,但是使用变量o能调用到的方法也是最少的,只能调用到Object中的声明的方法,因为变量o声明的类型就是Object.

注::java中的方法调用,是运行时动态和对象绑定的,不到运行的时候,是不知道到底哪个方法被调用的。


重写,重载和多态的关系


重载是编译时多态

调用重载的方法,在编译期间就要确定调用的方法是谁,如果不能确定则编译报错。

重写是运行时多态

调用重写的方法,在运行期间才能确定这个方法到底是哪个对象中的。这个取决于调用方法的引用,在运行期间所指向的对象是谁,这个引用指向哪个对象那么调用的就是哪个对象中的方法。(java中的方法调用, 是运行时动态和对象绑定的)


多态的注意事项


1.多态是方法的多态,属性没有多态性。

2.编写程序时,如果想调用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。但是如果两个没有关联的类进行强制转换,会报:ClassCastException。 比如:本来是狗,我把它转成猫。就会报这个异常。

3.多态的存在要有3个必要条件:要有继承,要有方法重写,父类引用指向子类对象。


多态存在的条件


1.有继承关系

2.子类重写父类方法

3.父类引用指向子类对象

补充一下第二点,既然多态存在必须要有“子类重写父类方法”这一条件,那么以下三种类型的方法是没有办法表现出多态特性的(因为不能被重写):

1.static方法,因为被static修饰的方法是属于类的,而不是属于实例的。

2.fifinal方法,因为被fifinal修饰的方法无法被子类重写。

3.private方法和protected方法,前者是因为被private修饰的方法对子类不可见,后者是因为尽管被protected修饰的方法可以被子类见到,也可以被子类重写,但是它是无法被外部所引用的,一个不能被外部引用的方法,怎么能谈多态呢。


方法绑定


执行调用方法时,系统根据相关信息,能够执行内存地址中代表该方法的代码。分为静态绑定和动态绑定。

静态绑定

在编译期完成,可以提高代码执行速度。

动态绑定

通过对象调用的方法,采用动态绑定机制。这虽然让我们编程灵活,但是降低了代码的执行速度。这也是JAVA比C/C++速度慢的主要因素之一。JAVA中除了fifinal类、fifinal方、static方法,所有方法都是JVM在运行期才进行动态绑定的。

多态:如果编译时类型和运行时类型不一致,就会造成多态。


instanceof****和类型转换


instanceof

public class Person{ public void run(){

} }

public class Student extends Person{

}

public class Teacher extends Person{

}

main:

Object o = new Student();

System.out.println(o instanceof Student);//true

System.out.println(o instanceof Person);//true

System.out.println(o instanceof Object);//true

System.out.println(o instanceof Teacher);//false

System.out.println(o instanceof String);//false

---------------------------

Person o = new Student();

System.out.println(o instanceof Student);//true

System.out.println(o instanceof Person);//true

System.out.println(o instanceof Object);//true

System.out.println(o instanceof Teacher);//false

//编译报错

System.out.println(o instanceof String);

---------------------------

Student o = new Student();

System.out.println(o instanceof Student);//true

System.out.println(o instanceof Person);//true

System.out.println(o instanceof Object);//true

//编译报错

System.out.println(o instanceof Teacher);

//编译报错

System.out.println(o instanceof String);

【分析1】

System.out.println(x instanceof Y);

该代码能否编译通过,主要是看声明变量x的类型和Y是否存在子父类的关系.有"子父类关"系就编译通过, 没有子父类关系就是编译报错.

之后学习到的接口类型和这个是有点区别的。

【分析2】

System.out.println(x instanceof Y);

输出结果是true还是false,主要是看变量x所指向的对象实际类型是不是Y类型的"子类型".

main:

Object o = new Person();

System.out.println(o instanceof Student);//false

System.out.println(o instanceof Person);//true

System.out.println(o instanceof Object);//true

System.out.println(o instanceof Teacher);//false

System.out.println(o instanceof String);//false

类型转换

public class Person{ public void run(){

}

}

public class Student extends Person{

public void go(){

}

}

public class Teacher extends Person{

}

【为什么要类型转换】

//编译报错,因为p声明的类型Person中没有go方法

Person p = new Student();

p.go();

//需要把变量p的类型进行转换

Person p = new Student();

Student s = (Student)p;

s.go();

或者//注意这种形式前面必须要俩个小括号

((Student)p).go();

【类型转换中的问题】

//编译通过 运行没问题

Object o = new Student();

Person p = (Person)o;

//编译通过 运行没问题

Object o = new Student();

Student s = (Student)o; //编译通过,运行报错 Object o = new Teacher(); Student s = (Student)o;

即: X x = (X)o;

运行是否报错,主要是变量o所指向的对象实现类型,是不是X类型的子类型,如果不是则运行就会报错。

【总结】

1.父类引用可以指向子类对象,子类引用不能指向父类对象。

2.把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转型。 如Father father = new Son();

3.把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转型。

如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即Son son =(Son) father;

其中father前面的(Son)必须添加,进行强制转换。

4.upcasting 会丢失子类特有的方法,但是子类overriding 父类的方法,子类方法有效。

5.向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。体现了JAVA的抽象编程思想。


修饰符

===

static****修饰符


1.static****变量

在类中,使用static修饰的成员变量,就是静态变量,反之为非静态变量。

静****态变量和非静态变量的区别

静态变量属于类的,"可以"使用类名来访问,非静态变量是属于对象的,"必须"使用对象来访问.

public class Student{

private static int age;

private double score;

public static void main(String[] args) {

Student s = new Student();

//推荐使用类名访问静态成员

System.out.println(Student.age);

System.out.println(s.age);

System.out.println(s.score);

}

}

静态变量对于类而言在内存中只有一个,能被类的所有实例所共享。实例变量对于类的每个实例都有一份, 它们之间互不影响.

public class Student{

private static int count;

private int num;

public Student() {

count++;

num++;

}

public static void main(String[] args) {

Student s1 = new Student();

Student s2 = new Student();

Student s3 = new Student();

Student s4 = new Student();

//因为还是在类中,所以可以直接访问私有属性

System.out.println(s1.num);

System.out.println(s2.num);

System.out.println(s3.num);

System.out.println(s4.num);

System.out.println(Student.count);

System.out.println(s1.count);

System.out.println(s2.count);

System.out.println(s3.count);

System.out.println(s4.count);

}

}

在加载类的过程中为静态变量分配内存,实例变量在创建对象时分配内存,所以静态变量可以使用类名来直接访问,而不需要使用对象来访问。

2.static****方法

在类中,使用static修饰的成员方法,就是静态方法,反之为非静态方法。

静态****方法和非静态方法的区别

静态方法数属于类的,"可以"使用类名来调用,非静态方法是属于对象的,"必须"使用对象来调用.

静态方法"不可以"直接访问类中的非静态变量和非静态方法,但是"可以"直接访问类中的静态变量和静态方法。

注意::this和super在类中属于非静态的变量.(静态方法中不能使用)

public class Student{

private static int count;

private int num;

public void run(){

}

public static void go(){

}

public static void test(){

//编译通过

System.out.println(count);

go();

//编译报错

System.out.println(num);

run();

}

}

非静态方法"可以"直接访问类中的非静态变量和非静态方法,也"可以"直接访问类中的静态变量和静态方法。

public class Student{

private static int count;

private int num;

public void run(){

}

public static void go(){

}

public void test(){

//编译通过

System.out.println(count);

go();

//编译通过

System.out.println(num);

run();

}

}

思考:为什么静态方法和非静态方法不能直接相互访问? 加载顺序的问题!

父类的静态方法可以被子类继承,但是不能被子类重写。

public class Person {

public static void method() {

}

}

//编译报错

public class Student extends Person {

public void method(){

}

}

例如:

public class Person {

public static void test() {

System.out.println(“Person”);

}

}

//编译通过,但不是重写

public class Student extends Person {

public static void test(){

System.out.println(“Student”);

}

}

main:

Perosn p = new Student();

p.test();

//输出Person

p = new Person();

p.test();

//输出Perosn

和非静态方法重写后的效果不一样

父类的非静态方法不能被子类重写为静态方法 ;

public class Person {

public void test() {

System.out.println(“Person”);

}

}

//编译报错

public class Student extends Person {

public static void test(){

System.out.println(“Student”);

}

}

3.代码块和静态代码块

【类中可以编写代码块和静态代码块】

public class Person {

{

//代码块(匿名代码块)

}

static{

//静态代码块

}

}

【匿名代码块和静态代码块的执行】

因为没有名字,在程序并不能主动调用这些代码块。

匿名代码块是在创建对象的时候自动执行的,**并且在构造器执行之前。**同时匿名代码块在每次创建对象的时候都会自动执行.

静态代码块是在类加载完成之后就自动执行,并且只执行一次。

注::每个类在第一次被使用的时候就会被加载,并且一般只会加载一次.

public class Person {

{

System.out.println(“匿名代码块”);

}

static{

System.out.println(“静态代码块”);

}

public Person(){

System.out.println(“构造器”);

}

}

main:

Student s1 = new Student();

Student s2 = new Student();

Student s3 = new Student();

//输出

静态代码块

匿名代码块

构造器

匿名代码块

构造器

匿名代码块

构造器

【匿名代码块和静态代码块的作用】

匿名代码块的作用是给对象的成员变量初始化赋值,但是因为构造器也能完成这项工作,所以匿名代码块使用的并不多。

静态代码块的作用是给类中的静态成员变量初始化赋值。

例如:

public class Person {

public static String name;

static{

name = “tom”;

}

public Person(){

name = “zs”;

}

}

main:

System.out.println(Person.name);

//tom

注:在构造器中给静态变量赋值,并不能保证能赋值成功,因为构造器是在创建对象的时候才指向,但是静态变量可以不创建对象而直接使用类名来访问.

4.创建和初始化对象的过程

Student s = new Student();

【Student类之前没有进行类加载】

1.类加载,同时初始化类中静态的属性 。

2.执行静态代码块。

3.分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null) 。

4.调用Student的父类构造器。

5.对Student中的属性进行显示赋值(如果有的话)。

6.执行匿名代码块。

7.执行构造器。

8.返回内存地址。

注:子类中非静态属性的显示赋值是在父类构造器执行完之后和子类中的匿名代码块执行之前的时候

public class Person{

private String name = “zs”;

public Person() {

System.out.println(“Person构造器”);

print();

}

public void print(){

System.out.println("Person print方法: name = "+name);

}

}

public class Student extends Person{

private String name = “tom”;

{

System.out.println(“Student匿名代码块”);

}

static{

System.out.println(“Student静态代码块”);

}

public Student(){

System.out.println(“Student构造器”);

}

public void print(){

System.out.println("student print方法: name = "+name);

}

public static void main(String[] args) {

new Student();

}

}

//输出:

Student静态代码块

Person构造器

student print方法: name = null

Student匿名代码块

Student构造器

Student s = new Student();

Student类之前已经进行了类加载

1.分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)

2.调用Student的父类构造器

3.对Student中的属性进行显示赋值(如果有的话)

4.执行匿名代码块

5.执行构造器

6.返回内存地址

5.静态导入

静态导包就是java包的静态导入,用import static代替import静态导入包是JDK1.5中的新特性。

意思是导入这个类里的静态方法。

好处:这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(…);就可以将其写入一个静态方法print(…),在使用时直接print(…)就可以了。但是这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便。

import static java.lang.Math.random;

import static java.lang.Math.PI;

public class Test {

public static void main(String[] args) {

//之前是需要Math.random()调用的

System.out.println(random());

System.out.println(PI);

}

}


final****修饰符


1.修饰类

用final修饰的类不能被继承,没有子类。

例如:我们是无法写一个类去继承String类,然后对String类型扩展的,因为API中已经被String类定义为final的了.

我们也可以定义fifinal修饰的类:

public final class Action{

}

//编译报错

public class Go extends Action{

}

2.修饰方法

用final修饰的方法可以被继承,但是不能被子类的重写。

例如:每个类都是Object类的子类,继承了Object中的众多方法,在子类中可以重写toString方法、equals方法等,但是不能重写getClass方法 wait方法等,因为这些方法都是使用fianl修饰的。

public class Person{ public final void print(){

}

}

//编译报错

public class Student extends Person{

public void print(){

}

}

3.修饰变量

用final修饰的变量表示常量,只能被赋一次值.其实使用fifinal修饰的变量也就成了常量了,因为值不会再变了

【修饰局部变量】

public class Person{

public void print(final int a){

//编译报错,不能再次赋值,传参的时候已经赋过了

a = 1;

}

}

public class Person{

public void print(){

final int a;

a = 1;

//编译报错,不能再次赋值

a = 2;

}

}

【修饰成员变量-非静态成员变量】

public class Person{

private final int a;

}

只有一次机会,可以给此变量a赋值的位置:

声明的同时赋值

匿名代码块中赋值

构造器中赋值(类中出现的所有构造器都要写)

【修饰成员变量-静态成员变量】

public class Person{

private static final int a;

}

只有一次机会,可以给此变量a赋值的位置:

声明的同时赋值

静态代码块中赋值

【修饰引用变量】

main:

final Student s = new Student();

//编译通过

s.setName(“tom”);

s.setName(“zs”);

//编译报错,不能修改引用s指向的内存地址

s = new Student();

abstract修饰符


abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

1.抽象类和抽象方法的关系

抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

2.语法

public abstract class Action{

public abstract void doSomething();

}

public void doSomething(){…}

对于这个普通方法来讲:

“public void doSomething()"这部分是方法的声明。

”{…}"这部分是方法的实现,如果大括号中什么都没写,就叫方法的空实现

声明 类的同时 , 加上 abstract 修饰符就是抽象类。

声明 方法的时候 , 加上 abstract 修饰符 , 并且去掉方法的大口号 , 同时结尾加上分号 , 该方法就是抽象方法。

3.特点及作用

抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。

抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

注:子类继承抽象类后,需要实现抽象类中没有实现的抽象方法,否则这个子类也要声明为抽象类。

public abstract class Action{

public abstract void doSomething();

}

main:

//编译报错,抽象类不能new对象

Action a = new Action();

//子类继承抽象类

public class Eat extends Action{

//实现父类中没有实现的抽象方法

public void doSomething(){

//code

}

}

main:

Action a = new Eat();

a.doSomething();

注:子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

4.思考

思考1:: 抽象类不能new对象,那么抽象类中有没有构造器?

抽象类是不能被实例化,抽象类的目的就是为实现多态中的共同点,抽象类的构造器会在子类实例化时调用,因此它也是用来实现多态中的共同点构造,不建议这样使用!

思考2:抽象类和抽象方法意义(为什么要编写抽象类、抽象方法)

打个比方,要做一个游戏。如果要创建一个角色,如果反复创建类和方法会很繁琐和麻烦。建一个抽象类后。若要创建角色可直接继承抽象类中的字段和方法,而抽象类中又有抽象方法。如果一个角色有很多种职业,每个职业又有很多技能,要是依次实例这些技能方法会显得想当笨拙。定义抽象方法,在需要时继承后重写调用,可以省去很多代码。总之抽象类和抽象方法起到一个框架作用。很方便后期的调用和重写抽象方法是为了程序的可扩展性。重写抽象方法时即可实现同名方法但又非同目的的要求。


接口

==

1.接口的本质


普通类:只有具体实现。

抽象类:具体实现和规范(抽象方法) 都有!

接口:只有规范!

【为什么需要接口?接口和抽象类的区别?】

1.接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。

2.抽象类还提供某些具体实现,接口不提供任何实现,接口中所有方法都是抽象方法。接口是完全面向规范的,规定了一批类具有的公共方法规范。

3.从接口的实现者角度看,接口定义了可以向外部提供的服务。

4.从接口的调用者角度看,接口定义了实现者能提供那些服务。

5.接口是两个模块之间通信的标准,通信的规范。如果能把你要设计的系统之间模块之间的接口定义好,就相当于完成了系统的设计大纲,剩下的就是添砖加瓦的具体实现了。大家在工作以后,做系统时往往就是使用“面向接口”的思想来设计系统。

【接口的本质探讨】

1.接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。

2.接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

3.OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计 模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。


2.接口与抽象类的区别


抽象类也是类,除了可以写抽象方法以及不能直接new对象之外,其他的和普通类没有什么不一样的。接口已经另一种类型了,和类是有本质的区别的,所以不能用类的标准去衡量接口。

声明类的关键字是class,声明接口的关键字是interface。

抽象类是用来被继承的,java中的类是单继承。

类A继承了抽象类B,那么类A的对象就属于B类型了,可以使用多态。

一个父类的引用,可以指向这个父类的任意子类对象。

注:继承的关键字是extends

接口是用来被类实现的,java中的接口可以被多实现。

类A实现接口B、C、D、E…,那么类A的对象就属于B、C、D、E等类型了,可以使用多态 。

一个接口的引用,可以指向这个接口的任意实现类对象。

注::实现的关键字是implements

**3.**接口中的方法都是抽象方法

写在最后

很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。

最后祝愿各位身体健康,顺利拿到心仪的offer!

由于文章的篇幅有限,所以这次的蚂蚁金服和京东面试题答案整理在了PDF文档里

蚂蚁、京东Java岗4面:原理+索引+底层+分布式+优化等,已拿offer

蚂蚁、京东Java岗4面:原理+索引+底层+分布式+优化等,已拿offer

蚂蚁、京东Java岗4面:原理+索引+底层+分布式+优化等,已拿offer

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

游戏。如果要创建一个角色,如果反复创建类和方法会很繁琐和麻烦。建一个抽象类后。若要创建角色可直接继承抽象类中的字段和方法,而抽象类中又有抽象方法。如果一个角色有很多种职业,每个职业又有很多技能,要是依次实例这些技能方法会显得想当笨拙。定义抽象方法,在需要时继承后重写调用,可以省去很多代码。总之抽象类和抽象方法起到一个框架作用。很方便后期的调用和重写抽象方法是为了程序的可扩展性。重写抽象方法时即可实现同名方法但又非同目的的要求。**


接口

==

1.接口的本质


普通类:只有具体实现。

抽象类:具体实现和规范(抽象方法) 都有!

接口:只有规范!

【为什么需要接口?接口和抽象类的区别?】

1.接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。

2.抽象类还提供某些具体实现,接口不提供任何实现,接口中所有方法都是抽象方法。接口是完全面向规范的,规定了一批类具有的公共方法规范。

3.从接口的实现者角度看,接口定义了可以向外部提供的服务。

4.从接口的调用者角度看,接口定义了实现者能提供那些服务。

5.接口是两个模块之间通信的标准,通信的规范。如果能把你要设计的系统之间模块之间的接口定义好,就相当于完成了系统的设计大纲,剩下的就是添砖加瓦的具体实现了。大家在工作以后,做系统时往往就是使用“面向接口”的思想来设计系统。

【接口的本质探讨】

1.接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。

2.接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

3.OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计 模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。


2.接口与抽象类的区别


抽象类也是类,除了可以写抽象方法以及不能直接new对象之外,其他的和普通类没有什么不一样的。接口已经另一种类型了,和类是有本质的区别的,所以不能用类的标准去衡量接口。

声明类的关键字是class,声明接口的关键字是interface。

抽象类是用来被继承的,java中的类是单继承。

类A继承了抽象类B,那么类A的对象就属于B类型了,可以使用多态。

一个父类的引用,可以指向这个父类的任意子类对象。

注:继承的关键字是extends

接口是用来被类实现的,java中的接口可以被多实现。

类A实现接口B、C、D、E…,那么类A的对象就属于B、C、D、E等类型了,可以使用多态 。

一个接口的引用,可以指向这个接口的任意实现类对象。

注::实现的关键字是implements

**3.**接口中的方法都是抽象方法

写在最后

很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。

最后祝愿各位身体健康,顺利拿到心仪的offer!

由于文章的篇幅有限,所以这次的蚂蚁金服和京东面试题答案整理在了PDF文档里

[外链图片转存中…(img-PxfJtRxI-1715140576848)]

[外链图片转存中…(img-fFSwhT1W-1715140576848)]

[外链图片转存中…(img-aHgqYtge-1715140576849)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 20
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值