Java修真之修炼斗技--入门面向对象

2024-03-16 18:40

本文主要是介绍Java修真之修炼斗技--入门面向对象,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 前言
    • 面向对象
      • 什么是面向对象?
        • 什么是对象?
        • 面向过程编程(POP)
        • 面向对象编程(OOP)
        • 面向过程和面向对象联系
        • 面向过程和面向对象优缺点
        • 什么是抽象(Abstract)?
        • 类和对象的关系
        • 面向对象三大特性
          • 封装(Encapsulation)
          • 继承(inheritance)
          • 多态(polymorphism)
      • 方法
        • 什么是方法?
        • 方法的定义
        • 方法调用
          • 静态方法
          • 非静态方法
          • 类中方法之间的调用
        • 调用方法时的传参
          • 形参和实参
          • 值传递和引用传递
        • 方法重载
      • 创建和初始化对象
      • 构造器
        • 构造器的两个特点:
        • 构造器的作用:
        • 构造器重载
        • 默认构造器
        • 内存分析
      • 封装
        • 封装概念
        • 封装的步骤
        • 作用和意义
      • 继承
        • 继承性质
        • Object类
        • Super关键字
        • 方法重写
          • 方法的重写(override)
          • 重写的语法
          • 为什么要重写?
      • 多态
        • 认识多态
        • 多态存在的条件
        • 重写、重载和多态的关系
      • 常用修饰符
        • Static修饰符
        • Final修饰符
          • 修饰类
          • 修饰方法
          • 修饰变量
        • Abstract修饰符
          • 抽象类和抽象方法的关系
          • 特点及作用
      • 接口
        • 接口的本质
        • 接口与抽象类的区别
        • 一个类可以实现多个接口
      • 总结

前言

在这里插入图片描述
在修真一途,以斗破苍穹来说,上一篇斗气筑基仅仅只是一个开始,有了少量的斗气后,那么也需要学会斗技,这样才能提升自己的实力。在学习Java 的时候也是如此,上一篇Java基础只是简单的入门,目前学习的“斗技”–面向对象,才是Java 的精髓。

斗技分天,地,玄,黄 四个等级,那么对应学习Java内容,应该也是从初级来开始,下面就跟着小曾一起来突破进阶把!

面向对象

什么是面向对象?

情景演绎
小伙伴:“小曾,小曾,什么是面向对象啊?”
我:“面向对象是一种编程思想,类似一种分类思维模式。Java的编程语言是面向对象的,采用这种语言进行编程称为面向对象编程(Object-OrientedProgramming, OOP)。”
小伙伴:“面向对象编程(OOP),是这样的吗?”
在这里插入图片描述
我:“那你这是只看到了表面,我们更应该透过现象看本质,真实具体的意思是:以类的方式组织代码,以对象的组织(封装)数据”
小伙伴:“那我有不太懂了,那什么是对象呢?”
在这里插入图片描述
我:“我反手就是一个尴尬而不失礼的微笑,没有对象可以自己创造对象。现在我们言归正传,面向对象的程序是由对象组成的, 每个对象包含对用户公开的特定功能部分和隐藏的实现部分。”
小伙伴:“那对象有什么属性,以及满足的主要特性?”
在这里插入图片描述
我:“顿时语塞,对象其实有三个主要特性,下面就请听我娓娓道来”

•对象的行为(behavior)—可以对对象施加哪些操作, 或可以对对象施加哪些方法?
•对象的状态(state )—当施加那些方法时,对象如何响应?
•对象标识(identity )—如何辨别具有相同行为与状态的不同对象?

什么是对象?

简单来说对象就是现实世界存在的任何事务都可以称之为对象,有着自己独特的个性。
在这里插入图片描述
面向对象就是构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

面向过程编程(POP)

面向过程编程(Procedure Oriented Programming):面向过程是按照固有顺序来执行代码。在设计方面,更多的考虑的数据结构应用及算法的应用。面向过程的可复用性和可维护性较低,适合于单兵作战,典型的语言就是C语言。
面向过程的思维模式:简单的线性思维,思考问题首先陷入第一步做什么、第二步做什么的细节中。这种思维模式适合处理简单的事情,比如:把大象装进冰箱,打开冰箱门,将大象塞进去,关上冰箱门。如果遇到比较复杂的事情,这种面向过程编程则比较不适合,比如:如何造神舟十号!

面向对象编程(OOP)

面向对象编程(Object Oriented Programming):是一种模块化的方式组织整体的逻辑结构,不用去关心具体的实现方式,只需要"按需调用可。
面向对象的思维模式:分类思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。

主要可以进行协作分工。比如:设计师分了10个类,然后将10个类交给了10个人分别进行详细设计和编码!

适用场景:如果一个问题需要多人协作一起解决,那么你一定要用面向对象的方式来思考!

面向过程和面向对象联系

对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

面向过程和面向对象优缺点

面向过程:
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展

面向对象:
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
缺点:性能比面向过程低

什么是抽象(Abstract)?

抽象:忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用关注细节。
例如:要设计一个学生成绩管理系统,那么对于学生,只关心他的班级、学号、成绩等,而不用去关心他的身高、体重这些信息。

抽象是什么?就是将多个物体共同点归纳出来,就是抽出像的部分!

类和对象的关系

类是一种抽象的数据类型,是构造对象的模板或蓝图;它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物.

直观理解:我们生活中所说的词语:动物、植物、手机、电脑等等。这些也都是抽象的概念,而不是指的某一个具体的东西。

同时类是用来描述/定义某一类具体的事物应该具备的特点行为对象是抽象概念的具体实例,比如 Person类、Pet类、Car类等

举例:张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念.

Student s = new Student(1L,"tom",20);
s.study();
Car c = new Car(1,"BWM",500000);
c.run();对象s就是Student类的一个实例,对象c就是Car类的一个具体实例,能够使用的是具体实例,而不是类。

类只是给对象的创建提供了一个参考的模板而已.

面向对象三大特性
封装(Encapsulation)

封装是面向对象的特征之一,是对象和类概念的主要特性。通俗点讲封装是把过程和数据包围起来,对数据的访问只能通过指定的方式。

注意点:在定义一个对象的特性的时候,有必要决定这些特性的可见性,即哪些特性对外部是可见的,哪些特性用于表示内部状态。通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

信息隐藏是用户对封装性的认识,封装则为信息隐藏提供支持。

优点:封装保证了模块具有较好的独立性,使得程序维护修改较为容易。主要表现在对应用程序的修改仅限于类的内部,因而可以将应用程序修改带来的影响减少到最低限度。

继承(inheritance)

继承:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
直观理解:你父亲给你留点钱,你继承过来,那么你也就有这么多钱。同理A继承B类,那么A类就有B类所有的属性以及功能。

子类或派生类:通过继承创建的新类
父类或基类:被继承的类、
关系:派生类(子类)可以从它的基类(父类)那里继承方法和实例变量,并且派生类(子类)中可以修改或增加新的方法使之更适合特殊的需要继承性很好的解决了软件的可重用性问题。

优点:让类与类之间产生关系,为多态打下基础;减少编码量,间接减少维护成本。

多态(polymorphism)

多态性:是指允许不同类的对象对同一消息作出响应,允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。

直观理解:有一个学习的方法,学习的对象是属于人的,但是人也是不同的,假如有一个学习好的小明和学习一般都小红,同样是一起执行学习的方法,但是最后学出来的东西是不太一样的。

总结:相同类域的不同对象,调用相同方法,表现出不同的结果。

实现多态的方式:覆盖 、重载

覆盖:是指子类重新定义父类的虚函数的做法
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

优点:接口重用;就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

方法

什么是方法?

Java方法是语句的集合,它们在一起执行一个功能。
比如我们常用的 System.out.println() 语句,println() 是一个方法;System 是系统类;out 是标准输出对象。

  • 方法是解决一类问题的步骤的有序组合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用

设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合,最重要的是保持方法的原子性【一个方法只完成1个功能】

优点:1、使程序变得更简短而清晰 ;2、有利于程序维护;3、可以提高程序开发的效率;4、提高了代码的重用性。

方法的定义

一般情况下,定义一个方法包含以下语法:

修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}

下面就一一介绍上述部分内容:

  • 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
  • 返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void
  • 方法名:是方法的实际名称。
  • 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。
  • 方法体:方法体包含具体的语句,定义该方法的功能。、

相信上面一大堆的名词,小伙伴们看的也比较不清晰,那就直接来个例子进行讲解:

demo1
功能:包含 2 个参数 num1 和 num2,它返回这两个参数的最大值
/** 返回两个整型变量数据的较大值 */
public static int max(int num1, int num2) {int result;if (num1 > num2)result = num1;elseresult = num2;return result;
}demo2
功能:加法
public int add(int num1, int num2) {return num1+num2;
}

加上异常类型格式:修饰符 返回类型 方1 法名(参数列表)异常抛出类型{...}

常用修饰符:public、static、abstract、final等等都是修饰符,一个方法可以有多个修饰符。
返回类型:方法执行完如果有要返回的数据,那么就要声明返回数据的类型,如果没有返回的数据,那么返回类型就必须写void.

注:break和return的区别
return 语句的作用
(1) return 从当前的方法中退出,返回到该调用的方法的语句处,继续执行
(2) return 返回一个值给调用该方法的语句返回值的数据类型必须与方法的声明中的返回值的类型一致。
(3) return后面也可以不带参数,不带参数就是返回空,其实主要目的就是用于想中断函数执行,返回调用函数处。
break语句的作用
(1)break在循环体内,强行结束循环的执行,也就是结束整个循环过程,不在判断执行循环的条件是否成立,直接转向循环语句下面的语句。
(2)当break出现在循环体中的switch语句体内时,其作用只是跳出该switch语句体。

异常抛出类型:如果方法中的代码在执行过程中,可能会出现一些异常情况,那么就可以在方法上把这些异常声明并抛出,也可以同时声明抛出多个异常,使用逗号隔开即可。

public void readFile(String file)throws IOException{
}public void readFile(String file)throws IOException,ClassNotFoundException{
}
方法调用
静态方法

使用static修饰符修饰的方法,就是静态方法.
调用这种方法的时候,"可以"使用对象调用,也"可以"使用类来调用,但是推荐使用类进行调用,因为静态方法是属于类的。(静态属性也是一样的)

可以直接调用
public class Student{public static void say(){}
}
main:
Student.say();
非静态方法

没有使用static修饰符修饰的方法,就是非静态方法.
调用这种方法的时候,是"一定"要使用对象的。因为非静态方法是属于对象的。(非静态属性也是一样的)

要使用new的实例化为对象
public class Student{public void say(){}
}
main:
//要使用new的实例化为对象
Student s = new Student();
s.say();
类中方法之间的调用
1、假设同一个类中有俩个方法,a方法和b方法,a和b都是非静态方法,相互之间可以直接调用。
public void a(){b();
}
public void b(){
}2、a和b都是静态方法,相互之间可以直接调用.
public static void a(){b();
}
public static void b(){
}3、a静态方法,b是非静态方法,a方法中不能直接调用b方法,但是b方法中可以直接调用a方法.静态方法不能
调用非静态方法!
public static void a(){//b();报错
}
public void b(){a();
}

总结:类中方法中的调用,两个方法都是静态或者非静态都可以互相调用,当一个方法是静态,一个方法是非静态的时候,非静态方法可以调用静态方法,反之不能。

调用方法时的传参
形参和实参
// a = x;
public void test(int a){//..
}
main:
int x = 1;
t.test(x);参数列表中的a是方法test的形参(形式上的参数)
调用方法时的x是方法test的实参(实际上的参数)
值传递和引用传递

值传递是实参把自己变量本身存的简单数值赋值给形参.
引用传递是实参把自己变量本身存的对象内存地址值赋值给形参.
【传递的东西的意义不一样】

值传递
public class Test{public static void changeNum(int a){a = 10;}public static void main(String[] args){int a = 1;System.out.println("before: a = "+a); //1changeNum(a);System.out.println("after: a = "+a); //1}
}输出的值都是1,为什么会这样?
因为changeNum是void 类型,返回值是空,所以就算a值发生改变,最后还是1
引用传递
public class Demo03 {public static void changeName(Student s){s.name = "tom";}public static void main(String[] args){Student s = new Student();System.out.println("before: name = "+s.name); //nullchangeName(s);System.out.println("after: name = "+s.name); //tom}
}
class Student{String name;
}经过changeName后返print的是tom,虽然changeName还是void 类型
但是用的实例s.name = tom,是相当于存在对象的内存里面,当调用的时候,就会打印出来。
方法重载

方法重载:类中有多个方法,有着相同的方法名,但是方法的参数各不相同,可以提供方法调用的灵活性。

方法重载必须满足以下条件:

  1. 方法名必须相同
  2. 参数列表必须不同(参数的类型、个数、顺序的不同)
public void test(Strig str){}
public void test(int a){}
public void test(Strig str,double d){}
public void test(Strig str){}
public void test(Strig str,double d){}
public void test(double d,Strig str){}
  1. 方法的返回值可以不同,也可以相同。

创建和初始化对象

使用new关键字创建对象
相信有些小伙伴应该听说过这句话,没有对象就new一个对象,一个对象不行,那就new两个。
在这里插入图片描述
使用new关键字创建的时候,除了分配内存空间之外,还会给 创建好的对象进行默认的初始化 以 及对类中构造器的调用

那么对main方法中的以下代码:// s对象就是一个Student类的具体实例Student s = new Student();

1)为对象分配内存空间,将对象的实例变量自动初始化默认值为0/false/null。(实例变量的隐式赋
值)
2)如果代码中实例变量有显式赋值,那么就将之前的默认值覆盖掉。(之后可以通过例子看到这个现象)
例如:显式赋值
private String name = “tom”;
3)调用构造器
4)把对象内存地址值赋值给变量。(=号赋值操作)

构造器

类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。

构造器的两个特点:
  1. 必须和类的名字相同
  2. 必须没有返回类型,也不能写void
构造器的作用:
  1. 使用new创建对象的时候,本质就是在调用构造器
  2. 构造器中的代码执行后,可以给对象中的属性初始化赋值
public class Student{private String name;public Student(){name = "tom";}
}
构造器重载

除了无参构造器之外,很多时候我们还会使用有参构造器,在创建对象时候可以给属性赋值.

public class Student{private String name;// 无参构造器,一般默认为空public Student(){name = "tom";}// 有参构造器public Student(String name){this.name = name;}
}
默认构造器

在编写类的时候没有写构造器,那么在编译之后也会自动的添加一个无参构造器,这个
无参构造器也被称为默认的构造器。

public class Student{
}
main:
//编译通过,因为有无参构造器
Student s = new Student();

如果我们手动编写构造器,那么近不会添加任何构造器了

public class Student{private String name;public Student(String name){this.name = name;}
}
main:
//编译报错,因为没有无参构造器
Student s = new Student();
内存分析

在这里插入图片描述
栈 stack:

  1. 每个线程私有,不能实现线程间的共享!
  2. 局部变量放置于栈中。
  3. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!

堆 heap:

  1. 放置new出来的对象!
  2. 堆是一个不连续的内存空间,分配灵活,速度慢!

方法区(也是堆):

  1. 被所有线程共享!
  2. 用来存放程序中永远是不变或唯一的内容。(类代码信息、静态变量、字符串常量)

相信如果只看上面的内容,不太容易理解,下面就以一个例子来进行简单介绍:
在这里插入图片描述
首先我们看到一段程序,是进入main方法,主要流程是
1、new了一个对象,调用右边程序的无参构造,生成了一个对象。、
在这里插入图片描述
具体过程:(1)首先我们在方法区定义Application类,将类中东西进行加载,main()方法,以及常量池,然后执行main方法,存在栈中 (2)main方法执行走到第一步,new pet(),加载到pet类,属性、方法存于方法区。(3)dog只是一个变量名,存在栈中,真正对象是在堆中生成。
在这里插入图片描述
2、给Pet对象赋值【旺财、3】
3、调用了Pet对象里面的shout()方法

堆和方法区的关系
方法区被包含于堆,是堆里面有一特殊区域。
在这里插入图片描述

封装

封装概念

形象化举例: 我们要看电视,只需要按一下开关和换台就可以了。有必要了解电视机内部的结构吗?有必要碰碰显像管吗?
制造厂家为了方便我们使用电视,把复杂的内部细节全部封装起来,只给我们暴露简单的接口,比如:电源开关。需要让用户知道的暴露出来,不需要让用户了解的全部隐藏起来。这就是封装。
封装:是把过程和数据包围起来,对数据的访问只能通过指定的方式。
特性:高内聚,低耦合
高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;
低耦合:仅暴露少量的方法给外部使用。

封装的步骤

主要内容:属性私有,get/set

  1. 使用private 修饰需要封装的成员变量。
  2. 提供一个公开的方法设置或者访问私有的属性;设置 通过set方法,命名格式: set属性名(); 属性的首字母要大写
//set负责给属性赋值
//get负责返回属性的值
public class Student{private String name;public void setName(String name){this.name = name;}public String getName(){return this.name;}
}
public class Test{public static void main(String[] args){Student s = new Student();s.setName("tom");System.out.println(s.getName());}
}
作用和意义
  1. 提高程序的安全性,保护数据。
  2. 隐藏代码的实现细节
  3. 统一用户的调用接口
  4. 提高系统的可维护性
  5. 便于调用者调用

继承

继承性质
  1. 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。

  2. 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。public class student extends Person{}

  3. 类和类之间的继承是单继承
    一个子类只能"直接"继承一个父类,就像是一个人只能有一个亲生父亲
    一个父类可以被多子类继承,就像一个父亲可以有多个孩子

  4. 父类中的属性和方法可以被子类继承
    子类中继承了父类中的属性和方法后,在子类中能不能直接使用这些属性和方法,是和这些属性和方法原有的修饰符(public protected default private)相关的。
    例如 :
    父类中的属性和方法使用public修饰,在子类中继承后"可以直接"使用
    父类中的属性和方法使用private修饰,在子类中继承后"不可以直接"使用

Object类

java中的每一个类都是"直接" 或者 "间接"的继承了Object类

System.out.println(任何对象 instanceof Object);
//输出结果:true
//注:任何对象也包含数组对象
例如:
//编译后,Person类会默认继承Object
public class Person{}
//Student是间接的继承了Object
public class Student extends Person{}

在Object类中,提供了一些方法被子类继承,那么就意味着,在java中,任何一个对象都可以调用这些被继承过来的方法。
例如:toString方法、equals方法、getClass方法等

Super关键字

子类继承父类之后,在子类中可以使用this来表示访问或调用子类中的属性或方法,使用super就表示访问或调用父类中的属性和方法。

访问父类中的属性
public class Person{protected String name = "zs";
}
public class Student extends Person{private String name = "lisi";public void tes(String name)t{System.out.println(name);System.out.println(this.name);System.out.println(super.name);}
}调用父类中的方法
public class Person{public void print(){System.out.println("Person");}
}
public class Student extends Person{public void print(){System.out.println("Student");}public void test(){print();this.print();super.print();}
}

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. 方法名必须相同
  2. 参数列表必须相同
  3. 访问控制修饰符可以被扩大,但是不能被缩小: public > protected > default > private
  4. 抛出异常类型的范围可以被缩小,但是不能被扩大
    ClassNotFoundException —> Exception
  5. 返回类型可以相同,也可以不同,如果不同的话,子类重写后的方法返回类型必须是父类方法返回
    类型的子类型
为什么要重写?

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

多态

认识多态

多态:同一方法可以根据发送对象不同而采用多种不同的行为方式。

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

  1. 一个对象的实际类型是确定的 例如: new Student(); new Person();
  2. 可以指向对象的引用的类型有很多
Person和Object都是Student的父类型
//student 能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
// Person 父类,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
注意:对象能够执行哪些方法,主要看对象左边的类型,和右边关系不大假如 Student有run类,Person也有run类
s2.run()  // 结果是得到的是子类run的结果,进行了方法的重写
多态存在的条件

1、有继承关系
2、子类重写父类方法
补充:三种类型不能被重写也就不能表现出多态特性

  • static方法,因为被static修饰的方法是属于类的,而不是属于实例的
  • final方法,常量,因为被final修饰的方法无法被子类重写
  • private 方法,私有的,没办法进行重写

3、父类指向子类对象

注意:多态是方法分多态,属性是没有多态性。

重写、重载和多态的关系

重载是编译时多态:调用重载的方法,在编译期间就要确定调用的方法是谁,如果不能确定则编译报错
重写是运行时多态:调用重写的方法,在运行期间才能确定这个方法到底是哪个对象中的。这个取决于调用方法的引用,在运行期间所指向的对象是谁,这个引用指向哪个对象那么调用的就是哪个对象中的方法。

重载和重写区别:
1、方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性
2、重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型。

常用修饰符

Static修饰符

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

静态变量属于类的,"可以"使用类名来访问,非静态变量是属于对象的,"必须"使用对象来访问.
public class Student{// 静态变量private static int age;// 非静态变量private double score;public static void main(String[] args) {// 生成S对象Student s = new Student();//推荐使用类名访问静态成员,如果是静态变量,可以直接使用类名访问Student.ageSystem.out.println(Student.age);// 用对象可以调用age和scoreSystem.out.println(s.age);System.out.println(s.score);}
}
Final修饰符
修饰类

用final修饰的类不能被继承,没有子类。
我们也可以定义final修饰的类:

public final class Action{}
//编译报错
public class Go extends Action{}
修饰方法

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

修饰变量

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

Abstract修饰符

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

抽象类和抽象方法的关系

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

特点及作用

抽象类,不能使用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();

接口

接口的本质

普通类:只有具体实现
抽象类:具体实现和规范(抽象方法) 都有!
接口:只有规范!

为什么需要接口?
接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离
抽象类还提供某些具体实现,接口不提供任何实现,接口中所有方法都是抽象方法。接口是完全面向规范的,规定了一批类具有的公共方法规范。

接口的本质:接口就是规范,定义的是一组规则;接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

接口与抽象类的区别

1、抽象类也是类,除了可以写抽象方法以及不能直接new对象之外,其他的和普通类没有什么不一样的。接口已经另一种类型了,和类是有本质的区别的,所以不能用类的标准去衡量接口
2、声明类的关键字是class,声明接口的关键字是interface
3、抽象类是用来被继承的,java中的类是单继承;接口是用来被类实现的,java中的接口可以被多实现。

一个类可以实现多个接口

使用implements可以实现多个接口,但是必须重写接口中的方法

public class Student implements A,B,C,D{//Student需要实现接口A B C D中所有的抽象方法//否则Student类就要声明为抽象类,因为有抽象方法没实现
}
main:
A s1 = new Student();
B s2 = new Student();
C s3 = new Student();
D s4 = new Student();

总结

相信大家如果把这篇文章看完,基本上Java的面向对象基础内容已经有所了解,小曾也跟着大家一起来书写这精彩的修仙之途。

这篇关于Java修真之修炼斗技--入门面向对象的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/816360

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定