上一篇我们讲到了Java的第一个程序HelloWorld
。并且用命令行的方式让程序在控制台输出了Hello World字样。这一篇,我们来大致说一下这段代码是如何运行起来的。
首先,所有的Java程序,都必须要有一个称之为“主方法”的函数入口,这个入口便是public static void main(String []args)
方法(我们将它简称为main
方法)。也就是说,要让一个Java程序运行起来,就必须通过main
方法才可以执行一系列的操作与运算,最终达到目的需求。
一段代码的组成需要类名、变量名、和方法名,可以统称为Java的标识符。
-
所有的标识符都应该以字母(A-Z、a-z)、数字、美元符($)、或者下划线(_)组成
-
首字符只能以字母、$、下划线(_)开头
-
Java所定义的“关键字”不能作为标识符使用
-
标识符大小写敏感,如age和Age是由区别的
//正确的标识符命名:
bboyHan、_bboyHan、_bboy_$_23_han
//错误的命名:
23bboy、+23han、bboy&
1.1中提到了标识符的命名不能以“关键字”进行命名,我们来看一下Java的关键字有哪些:
类别 | 关键字 | 说明 | 关键字 | 说明 |
---|---|---|---|---|
访问控制 | private | 私有的 | public | 公共的 |
protected | 受保护的 | |||
类、方法和变量修饰符 | abstract | 声明抽象 | new | 新,创建 |
class | 类 | static | 静态 | |
extends | 扩充,继承 | strictfp | 严格,精准 | |
final | 最终值,不可改变的 | synchronized | 线程,同步 | |
implements | 实现(接口) | transient | 短暂 | |
interface | 接口 | volatile | 易失 | |
native | 本地,原生方法(非 Java 实现) | |||
程序控制语句 | break | 跳出循环 | case | 定义一个值以供 switch 选择 |
continue | 继续 | while | 循环 | |
default | 默认 | switch | 根据值选择执行 | |
do | 运行 | return | 返回 | |
else | 否则 | instanceof | 实例 | |
for | 循环 | if | 如果 | |
错误处理 | assert | 断言表达式是否为真 | try | 捕获异常 |
catch | 捕捉异常 | throws | 声明一个异常可能被抛出 | |
finally | 有没有异常都执行 | throw | 抛出一个异常对象 | |
包相关 | import | 引入 | ||
package | 包 | |||
基本类型 | boolean | 布尔型 | short | 短整型 |
byte | 字节型 | long | 长整型 | |
char | 字符型 | int | 整型 | |
double | 双精度浮点 | float | 单精度浮点 | |
变量引用 | super | 父类,超类 | void | 无返回值 |
this | 本类 | |||
保留关键字 | goto | 是关键字,但不能使用 | null | 空 |
const | 是关键字,但不能使用 |
既然说Java是一个面向对象的设计语言,那什么是面向对象?
提到“面向对象”,就必然会提到“面向过程”。面向过程(Procedure Oriented),就是计算机执行一段“过程化”的叙事思维,比如说“打开电脑”这个动作,“电脑”作为对象的参数传入方法中,然后在方法内定义打开电脑的具体步骤。而面向对象(Object Oriented),是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。还以“打开电脑”这个例子来说,面向对象的编程,就是将电脑抽象出来,定义电脑的相关属性(如大小、CPU、各种硬件组成)和操作行为(如开机、关机、重启),进而解决这一问题。
Java之父Gosling设计的Object类,是任何类的默认父类,即是万事万物的抽象,高度概括了事物的自然行为和社会行为。类相当于是某个具体事物的进一步抽象。如Iphone、小米、华为P30可以统称为“手机类”,王者农药、吃鸡、消消乐都是“游戏类”。对象,就是这其中一个个具体的事物,如Iphone是一个对象,小米是一个对象。
类的定义由访问级别、类型、类名、是否抽象、是否静态、泛型标识、继承等组成。类型分为class、enum(枚举)、interface(接口),类的访问级别有public和无访问控制符。
面向对象编程,就是一个对象先抽象出模型,在定义共性特征和行为,进而解决实际问题。
- 变量
Java的变量,我们可以把它理解为一个对象的属性特征,比如小米手机,它有长宽高、重量、使用寿命、内存等等。
- 方法
是指对象的操作行为,比如小米手机可以打电话、开机、关机、充电等等。
- 修饰符
Java通过对变量和方法进行不同的修饰,可以做到将对象的行为和属性进行对外或对内的访问限制,即公有化、私有化。如我的小米手机需要指纹才能解锁、我的电话通讯录只有我才能看,手机外观所有人都可以看到......Java可以使用修饰符来修饰类中方法和属性。主要有两类修饰符:
**访问修饰符:**Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。
访问权限 | public | protected | default | private |
---|---|---|---|---|
同一个类 | yes | yes | yes | yes |
同一个包 | yes | yes | yes | no |
子类 | yes | yes | no | no |
其它类 | yes | no | no | no |
**非访问修饰符:**为了实现一些其他的功能,Java 也提供了5种非访问修饰符。
修饰符 | 说明 |
---|---|
static | 静态修饰符,修饰类方法和类变量。 |
final | 最终修饰符,修饰类、方法和变量,修饰的类不能够被继承,修饰的方法不能被重新定义,修饰的变量表示为不可修改的常量。 |
abstract | 抽象修饰符,用来创建抽象类和抽象方法。 |
synchronized | 修饰符,用于线程编程。 |
transient | 修饰符,用于跳过序列化对象中特定的敏感变量 |
volatile | 修饰符,用于线程编程。 |
注意点:所谓friendly/default,即指的是在类前不加任何修饰符的情况,并不是真的有这样一个“修饰符”。
修饰符修饰类、方法和变量的详细列表
类别 | 修饰符 | 说明 |
---|---|---|
类修饰符 | public | 将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类。 |
abstract | 将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现。 | |
final | 将一个类生命为最终(即非继承类),表示他不能被其他类继承。 | |
friendly | 默认的修饰符,只有在相同包中的对象才能使用这样的类。 | |
成员变量修饰符 | public | 指定该变量为公共的,他可以被任何对象的方法访问。 |
private | 私有访问控制符,指定该变量只允许自己的类的方法访问,其他任何类(包括子类)中的方法均不能访问。 | |
protected | 保护访问控制符,指定该变量可以别被自己的类和子类访问。在子类中可以覆盖此变量。 | |
friendly | 在同一个包中的类可以访问,其他包中的类不能访问。 | |
final | 最终修饰符,指定此变量的值不能变。 | |
static | 静态修饰符,指定变量被所有对象共享,即所有实例都可以使用该变量。变量属于这个类。 | |
transient | 过度修饰符,让某些被修饰的成员属性变量不被序列化。 | |
volatile | 易失修饰符,指定该变量可以同时被几个线程控制和修改。 | |
方法修饰符 | public | 公共控制符 |
private | 私有控制符,指定此方法只能有自己类等方法访问,其他的类不能访问(包括子类) | |
protected | 保护访问控制符,指定该方法可以被它的类和子类进行访问。 | |
final | 指定该方法不能被重载。 | |
static | 指定不需要实例化就可以激活的一个方法。 | |
synchronize | 同步修饰符,在多个线程中,该修饰符用于在运行前,对他所属的方法加锁,以防止其他线程的访问,运行结束后解锁。 | |
native | 本地修饰符。指定此方法的方法体是用其他语言在程序外部编写的。 | |
void | 无返回值 |
定义一个类
//定义一个小米手机类
public class XiaoMi{
//定义属性
public int weight; //重量,所有人可看,用public修饰
private List phoneList; //联系人列表,仅自己可见,用private修饰
//定义方法
public void callPhone(String phoneNumber){
//...打电话
}
private void unlockPhone(String password){
//...指纹解锁
}
}
有了面向对象的编程思想之后,就具备了一定的建模能力。将现实中的一些具体业务进行“抽象”,通过一定的项目实践,积累经验。便可掌握Java编程过程中的一大关键要素。抽象,是面向对象思想最基本的能力之一,正确而严谨的业务抽象和建模分析能力,便是后续的封装、继承、多态的基础。
Java编程中,必须了解面向对象的三大特性,即封装、继承、多态
封装
封装思想的核心,就是“隐藏细节”、“数据安全”:将对象不需要让外界访问的成员变量和方法私有化,只提供符合开发者意愿的公有方法来访问这些数据和逻辑,保证了数据的安全和程序的稳定。
实现思路:
使用 private 修饰符把成员变量设置为私有,防止外部程序直接随意调用或修改成员变量,然后对外提供public 的 set 和 get 方法按照开发者的意愿设置和获取成员变量的值。
- a、修改属性的可见性——设为private;
- b、创建getter/setter方法,用于属性的读写;
- c、在getter/setter方法中加入属性控制语句,对属性值的合法性进行判断。
补充: 既然通过getter/setter方法来进行读取和修改,那与直接对属性进行操作有什么区别?
答: 在实际场景中,我们通常会在setter方法对属性赋值过程中,进行其他的一些操作(如鉴权控制、日志记录、参数验证等),而直接对属性进行修改是无法做到的。
class People{
private int age;
public void setAge(int age){
//...其它逻辑
this.age = age;
}
public int getAge(){
//...其它逻辑
return age;
}
public void doWork(){
//做一些事
}
}
继承
继承是类与类的一种关系,例如:动物和狗的关系,动物是父类(或基类),狗是子类(或派生类)。要注意的是,在Java中的继承是单继承,也就是说一个儿子只能有一个爸爸,一个子类只允许有一个父类。
使用继承的优势在于,子类拥有父类的所有属性和方法(private除外),并且子类可以复用父类的代码。
使用继承,创建出具有逻辑等级结构的类体系,形成一个继承Tree,对后续的业务使用和代码复用可以带来非常大的便利。
多态
多态,是指运行时的实际对象类型,在同一个方法下产生不同的运行结果,使得同一个行为具有不同的表现形式。
class Student extends People{
public void doWork(){
//做作业
}
}
class Worker extends People{
public void doWork(){
//上班
}
}
补充:
多态的体现在于子类继承父类后,不满足父类方法的基本要求,而进行“覆写”(override)完善。在这里,初学者朋友经常会将override
与overload
相互混淆。
-
override: 指的是重写父类方法,返回值类型、方法名、参数类型及个数,都与从父类继承的方法相同。
-
overload: 重载,指的是方法名相同,但参数类型或参数个数不同。
Java的多态,指在编译层面无法确定最终调用的方法体,以**“覆写”(override)为基础来实现面向对象的特性,在运行期由JVM进行动态绑定,调用合适的覆写方法体来执行。而重载(overload)**则是编译器确定的方法调用,属于静态绑定。本质上二者毫不相干也毫无关联!!