Java快速入门(五)
Java修饰符
访问权限修饰符
-
用于控制一个类的成员是否可以在其它类中访问,不能修饰局部变量
-
private
(当前类访问权限):在同一类内可见,只能被所属类访问 (包访问权限):不使用任何修饰符时,在同一包内可见
protected
(子类访问权限):对同一包内的任何其它类和不同包中的子类可见,不能修饰接口中的成员变量和成员方法(注意:在不同包中的子类只能通过该子类访问父类中protected
成员,通过其它子类或父类都无法访问)public
(公共访问权限):对所有类可见
非访问修饰符
static
用来创建类方法和类变量,类方法不能访问的实例变量final
用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,不可修改abstract
用来创建抽象类、抽象方法synchronized
修饰的方法、代码块在同一时间只能被一个线程访问,不能修饰构造器、成员变量等volatile
修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值;并且,当成员变量发生变化时,强迫线程将变化值回写到共享内存(保证了线程操作时变量的可见性,即一个线程修改了某个变量的值,这新值对其它线程来说是立即可见的)(只能保证内存可见性,无法保证操作的原子性)transient
序列化的对象包含被 transient 修饰的实例变量时,JVM 跳过该特定的变量native
修饰的方法通常采用 C/C++ 语言来实现
volatile 的实现原理
- 如果对声明了 volatile 变量进行写操作,JVM 就会向处理器发送一条 Lock 前缀的指令,将这个变量所在缓存行的数据写回到内存,这个写回内存的操作会引起在其它 CPU 里缓存了该内存地址的数据无效
- 缓存一致性协议(如 Intel 的 MESI 协议):每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里
final 修饰符
final 修饰的类
- 表示最终的类,不可被继承的类
- java 里
final
修饰的类有很多,比如八大基本数据类型包装类和 String 类,也是不可变类(当创建它们的实例后,其实例的实例变量不可改变)
final 修饰的方法
- 最终的方法,该方法子类可以调用,但不允许被子类覆盖
- 构造方法不能使用
final
修饰
final 修饰的变量
- 最终的变量,常量,该变量只能被赋值一次
final
修饰的成员变量必须显式指定初始值(定义时、初始化块或构造器中指定),系统不会为 final 字段初始化;静态常量的单词全部大写,单词间使用下划线隔开final int MAX_VALUE = …;
final
是唯一可以修饰局部变量的修饰符final
修饰基本类型的变量,表示该变量不能被重新赋值-
final
修饰引用类型的变量,表示该变量所引用的地址不能变,而所引用对象的内容可以改变 -
可执行“宏替换”的 final 变量:当定义 final 变量时就为该变量指定了初始值,编译器会把程序中所有用到该变量的地方直接替换成该变量的值(在编译阶段能确定的内容只能来自于常量池中)
面向对象思想
面向对象是一种符合人类思维习惯的编程思想。现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。
提到面向对象,自然会想到面向过程,面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一一实现,使用的时候依次调用就可以了。面向对象则是把构成问题的事务按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。当然,一个应用程序会包含多个对象,通过多个对象的相互配合来实现应用程序的功能,这样当应用程序功能发生变动时,只需要修改个别的对象就可以了,从而使代码更容易得到维护。面向对象的特点主要可以概括为封装性、继承性和多态性。
1、封装性
封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装思想。例如,用户使用电脑,只需要使用手指敲键盘就可以了,无需知道电脑内部是如何工作的,即使用户可能碰巧知道电脑的工作原理,但在使用时,并不完全依赖电脑工作原理这些细节。
2、继承性
继承性主要描述的是类与类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有类的功能进行扩展。例如,有一个汽车的类,该类中描述了汽车的普通特性和功能,而轿车的类中不仅应该包含汽车的特性和功能,还应该增加轿车特有的功能,这时,可以让轿车类继承汽车类,在轿车类中单独添加轿车特性的方法就可以了。继承不仅增强了代码的复用性、提高开发效率,还为程序的维护补充提供了便利。
3、多态性
多态性指的是在程序中允许出现重名现象,它指在一个类中定义的属性和方法被其它类继承后,它们可以具有不同的数据类型或表现出不同的行为,这使得同一个属性和方法在不同的类中具有不同的语义。例如,当听到“Cut” 这个单词时,理发师的行为是剪发,演员的行为表现是停止表演,不同的对象,所表现的行为是不一样的。
1 面向对象思想引入
面向对象的编程思想,力图让程序中对事物的描述与该事物在现实中的形态保持一致。为了做到这一点,面向对象的思想中提出了两个概念,即类和对象。其中,类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体。
前面我们讲过数组,当有多个数组都需要遍历时,我们可以将遍历的代码封装到方法中,需要遍历时,就调用相应的方法即可,提高代码的复用性。在对数组遍历的基础上继续增加需求,比如获取最值,数值逆序等,同样需要将这些功能封装到相应的方法中。这样继续封装会发现方法越来越多,于是就想能不能将这些方法继续进行封装呢?通过前面的讲解我们知道类是可以存放方法的,所以,我们就考虑使用类封装来这多个方法,将来再做数组的操作时,不用去找具体的方法,先找到这个类,然后使用这个类中的方法。这就是面向对象思想的编程方式。
1.2 面向过程思想概述
我们来回想一下,这几天我们完成一个需求的步骤:首先是搞清楚我们要做什么,然后在分析怎么做,最后我们再代码体现。一步一步去实现,而具体的每一步都需要我们去实现和操作。这些步骤相互调用和协作,完成我们的需求。
在上面的每一个具体步骤中我们都是参与者,并且需要面对具体的每一个步骤和过程,这就是面向过程最直接的体现。
那么什么是面向过程开发呢? 面向过程开发,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求。
面向过程的代表语言:C语言,强调的是每一个功能的步骤
1.3 面向对象思想概述
当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了,这时就开始思索,能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。这样结构就清晰了很多。用的时候,找到对应的类就可以了。这就是面向对象的思想。接下来我们看看面向对象到底是什么?
面向对象思想概述:面向对象是基于面向过程的编程思想,强调的是对象,然后由对象去调用功能。
面向对象思想特点
- 是一种更符合我们思想习惯的思想
- 可以将复杂的事情简单化
- 将我们从执行者变成了指挥者,角色发生了转换
举例:
(1) 买电脑: 面向过程:我的了解电脑—了解我自己的需求—找对应的参数信息—去中关村买电脑—讨价还价—买回电脑
面向对象:我知道我要买电脑 — 班长去给我买 — 班长就买回来了
(2) 洗衣服:
面向过程:把衣服脱下—找一个盆—放点洗衣粉—加点水—把衣服扔进去—搓一搓—清洗衣服—拧干—晾起来
面向对象:把衣服脱下—打开全自动洗衣机—扔进去—一键即可—晾起来
(3) 吃饭:
面向过程:去超市买菜—摘菜—洗菜—切菜—炒菜—盛起来—吃
面向对象:上饭店吃饭,你—服务员(点菜)—厨师(做菜)—服务员(端菜)—吃
1.4 面向对象开发、设计、特征
面向对象开发:就是不断的创建对象,使用对象,指挥对象做事情。 面向对象设计:其实就是在管理和维护对象之间的关系。
面向对象特征
- 封装(encapsulation)
- 继承(inheritance)
- 多态(polymorphism)
2. 类与对象及其使用
2.1 类与对象的关系
我们学习编程语言,就是为了模拟现实世界的事物,实现信息化。比如:去超市买东西的计费系统,去银行办业务的系统。
我们如何表示一个现实世界事物呢:
- 属性 就是该事物的描述信息
- 行为 就是该事物能够做什么
- 举例:学生事物
我们学习的Java语言最基本单位是类,所以,我们就应该把事物用一个类来体现。
类:是一组相关的属性和行为的集合 对象:是该类事物的具体体现 举例:类 学生,对象班长就是一个对象
PS 类:可以理解为构造对象的一个蓝图或者模版,是抽象的概念 对象:是以类为模型创建的具体实例,是对类的一种具体化。
2.2 类的定义
现实世界的事物有属性(人的身高,体重等)和行为(人可以学习,吃饭等)
Java中用class描述事物也是如此,成员变量 就是事物的属性,成员方法 就是事物的行为
定义类其实就是定义类的成员(成员变量和成员方法)
-
对象是类的实例,类是对象的抽象
-
类可被认为是一种自定义的数据类型,可以使用类来定义变量
-
类中的成员:字段(成员变量)、构造器、方法、初始化块、内部类(包括接口、枚举)
-
外部类只能有两种访问控制级别:public 和 缺省
-
定义类的语法格式
java [修饰符] class 类名 { 0-N 成员变量(字段) // 描述类具有的特性,对象的状态 0-N 构造器定义 0-N 方法 // 描述类具有的功能,对象的行为 }
对象的创建和操作
-
对象实例化过程:
- 根据类及其父类的字段在堆中为该对象的所有实例变量分配内存;
- 对这些实例变量执行初始化,其初始化顺序是:先执行初始化块或声明实例变量时指定的初始值(它们的执行顺序与它们在源代码中的排列顺序相同),再根据传入的实参列表执行对应构造器里指定的初始值;
- 由 new 运算符返回对象的引用地址 给 该对象的引用变量(栈内存)。
-
类或实例访问成员变量或方法的语法:类.类变量|方法 或者 实例.实例变量|方法
java // 定义一个 Person 类 class Person { String name; void coding() {} // 测试类 class PersonDemo { public static void main(String[] args) { Person p = new Person(); // 创建一个对象 p p.name = "Admin"; p.coding(); } }
-
static 修饰符
-
static
修饰的成员(
类成员
:类变量、类方法、静态初始化块、静态内部类)
- 随着所在类的加载而加载,优先于该类对象存在(当字节码被加载进 JVM 时类成员就存在了,而对象是后来 new 出来的)
- 被该类所有对象所共享
- 可以直接用类名调用
-
无
static
修饰的成员(实例成员:实例变量、实例方法、普通初始化块、实例内部类) -
static 修饰的成员(属于类)及构造器不能直接访问没有 static 修饰的成员(属于对象)
-
局部变量不属于任何类或实例,不能使用 static 修饰;不能修饰构造器
-
static 修饰的方法中不能使用 this 或 super 引用(static 强调的是类,this 和 super 强调的是对象)
this 关键字
当一个对象创建之后,JVM 会分配一个引用自身的引用:this
存在位置
- 构造方法中,代表正在初始化的对象
- 实例方法中,代表调用此方法的对象
使用 this
- 构造器重载时的互调
this([参数]);
(必须作为构造方法中的第一条语句),一般地,是少参数的构造器调用多参数的构造器(将功能都写在多参数的构造器中) - 解决实例方法中成员变量和参数(局部变量)之间的二义性,必须使用
- 同类中实例方法间互调(调用者是 this,不建议省略)
- 实例方法将 this 作为参数传递给另一个方法
- 将 this 作为方法的返回值(链式方法编程)
构造器
作用
- 创建对象(必须和 new 一起使用,通过 new 关键字来调用某个类的构造器)
- 完成对象字段(实例变量)的初始化(手动赋值)
特点
- 构造器名与类名相同(首字母大写)
- 不用定义返回值类型(缺省的返回值类型是当前类)
- 构造器体中不需要 return 语句(缺省的返回值是当前创建对象的引用)
默认构造器
编译器在编译源文件的时候产生的缺省的构造器
- 符合构造器体特点
- 没有形参
- 没有构造器体
- 访问权限修饰符与所在类的访问权限修饰符相同
- 显式定义了构造器之后,默认的构造器就没有了
构造器的重载
public class Person {
private String name;
private int age;
/* 默认构造器(编译器产生的)
public Person() {}
*/
// 创建对象,初始化 name
public Person(String name) {
this(name, 0);
}
// 创建对象,初始化 name 和 age
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 此处省略 name 和 age 的 setter 和 getter 方法
}
class PersonDemo {
public static void main(String[] args) {
Person p = new Person("Admin", 28); // 创建对象 p,并初始化
}
}
封装(Encapsulation)和隐藏
- 把对象的状态和行为封装成一个整体,隐藏对象的内部信息和实现细节,不允许外部直接访问,对外暴露方法来实现对内部信息的操作和访问
- 优点:安全性、重用性、低耦合性
- 一般地,字段使用
private
修饰(私有化),拥有实现细节的方法使用private
修饰,一般的方法使用public
修饰
public class Person {
private String name; // 字段使用 private 私有
private boolean man;
// 提供 public 修饰的 getter、setter 方法访问本类中的私有字段
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isMan() {
return man;
}
public void setMan(boolean man) {
this.man = man;
}
}
class PersonDemo {
public static void main(String[] args) {
Person p = new Person; // 通过无参数构造器创建对象 p
p.setName("Sdky");
p.setMan(true);
}
}
设置和获取对象的数据
- 创建对象并给对象设置初始值的两种方式:
- setter 注入(属性注入):先通过无参数构造器创建出一个对象,再通过对象调用相应的 setter 方法
- 构造注入:直接调用带参数的构造器,创建对象的同时完成对象字段的初始化
- 获取对象的数据:getter 方法
package、import 和 import static
package 语句
- 作用:把一个类放在指定的包结构下
- 包命名规则:域名倒写.模块名.组件名
-
语法格式
-
编译命令:javac -d . PackageDemo.java // 表示在当前路径下先生成与包名层次相应的文件结构,再在包下生成字节码文件(如果编译 Java 文件时不使用 -d 选项,编译器不会为 Java 源文件生成相应的文件结构)
- 运行命令:java com.example.hello.PackageDemo
- Java 的常用包
- java.lang:Java 语言的核心类,如 String、Math、System 和 Thread 类等
- java. util:Java 的大量工具类/接口和集合框架类/接口,如 Arrays 和 List、Set 等
- java. net:Java 网络编程相关的类/接口
- java.io:Java 输入/输出编程相关的类/接口
- java. text:Java 格式化相关的类
- java.sql:Java 进行 JDBC 数据库编程的相关类/接口
- java. awt:抽象窗口工具集的相关类/接口,用于构建图形用户界面(GUI)程序
- java.swing:Swing 图形用户界面编程的相关类/接口,用于构建平台无关的 GUI 程序
import 语句
- 类的全限定名:包名.类名 java.util.Arrays
- 在一个类中使用非同包的类和非 java.lang 包下的类,要使用类的全限定名
- 使用 import 可以省略写包名;而使用 import static 则可以连类名都省略
- import 语句应该出现在 package 语句(如果有的话)之后、类定义之前
- 导入指定包下某个类或全部类
import java.util.Arrays; // 导入 java.util 包下的 Arrays 类import java.util.*; // 导入 java.util 包下所有被当前类使用到的类
- 注意:Java 默认为所有源文件导入 java.lang 包下的所有类,但不包括其子包下的类
- 导入指定类中的
static
成员(语法糖),但无法导入与 java.lang.Object 类中的方法名相同的方法,如 toString,equals
// import static 类的全限定名.该类中的 static 成员名;
import static java.util.Arrays.sort;
import static java.util.Arrays.*;