1、封装
定义
封装就是把对象的属性(状态)和方法(行为)结合在一起,并尽可能隐蔽对象的内部细节,成为一个不可分割的独立单位(即对象),对外形成一个边界,只保留有限的对外接口使之与外部发生联系。
原则
-
使对象以外的部分不能随意存取对象的内部数据,从而有效的避免了外部错误对它的“交叉感染”。
-
数据隐藏特性提升了系统安全性,使软件错误能够局部化,减少查错和排错的难度。
2、类
定义
类就是对象的模板,而对象就是类的一个实例 。
类由属性和方法构成:
- 对象的特征在类中表示为成员变量,称为类的属性。
- 类的方法是对象执行操作的一种规范。方法指定以何种方式操作对象的数据,是操作的实际实现。
类的实现
[访问符] [修饰符] class <类名>{
[属性]
[方法]
}
//声明一个类,定义一个长方形(Rectangle)类,有长、宽属性,对每个属性都提供相应的get/set方法
public class Rectangle {
/* 长方形宽度 */
private double width;
/* 长方形高度 */
private double length;
/* 成员变量对应的方法 */
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
}
对象的创建
要获得一个类的对象一般需要两步:
- 声明该类类型的一个变量。
- 创建该对象(即在内存中为该对象分配地址空间),并把该对象的引用赋给声明好的变量。这是通过使用new运算符实现的。
类的构造方法
- 构造方法是一种特殊的方法,在对象被创建时用来初始化对象;
- 它具有和它所在的类完全一样的名字
- 构造方法和类的方法类似,只不过构造方法没有返回类型;
- 构造方法的任务是初始化一个对象的内部状态
- 如果在Java程序中没有定义任何的构造方法,则编译器将会自动加上一个不带任何参数的构造方法即缺省构造方法,该方法不存在于源程序中,但可以使用。
public class Rectangle {
private double width;
private double length;
/* 利用width和length创建构造方法 */
public Rectangle (double width, double length) {
this.width = width;
this.length = length;
}
}
this对象的使用
this关键字代表当前所在类的对象,即本类对象,用于解决变量的命名冲突和不确定性问题;在没有同名的情况下,可以直接使用属性的名字。
参数传递
按值传递
按值传递(call by value) ,将要传递的参数的值传递给被调方法,被调方法通过创建一份新的内存拷贝来存储传递的值,然后在内存拷贝上进行数值操作,所以按值传递不会改变原始参数的值。一般传递的参数为基本数据类型(数值,字符)会自动采用按值传递
public static void main(String[] args) {
int num = 5;
System.out.println("调用change方法前 : " + num);
//创建一个CallByValue类型的对象
CallByValue callByValue = new CallByValue();
callByValue.change(num);
System.out.println("调用change方法后 : " + num);
}
/*定义change方法*/
public void change(int num) {
num += 5;
System.out.println("在change中 num的值为 : " + num);
}
//执行结果如下:
调用change方法前 : 5
在change中 num的值为 : 10
调用change方法后 : 5
引用传递
引用传递是将参数的引用传递给被调方法,被调方法通过传递的引用值获取其指向的内存空间,从而在原始内存空间上直接进行操作,即实参和形参指向内存中同一空间。一般传递的参数为对象时会自动采用引用传递。
class CallByRef {
int a, b;
CallByRef(int i, int j) {
a = i;
b = j;
}
void change(CallByRef obj) {
obj.a = 50;
obj.b = 40;
System.out.println("在change方法中 obj.a=" + obj.a + ",obj.b=" + obj.b);
}
}
public class Test {
public static void main(String[] args) {
CallByRef obj = new CallByRef(15, 20);
System.out.println("调用change方法前 obj.a=" + obj.a + ",obj.b=" + obj.b);
obj.change(obj);
System.out.println("调用change方法后 obj.a=" + obj.a + ",obj.b=" + obj.b);
}
}
//执行结果如下:
调用change方法前 obj.a=15,obj.b=20
在change方法中 obj.a=50,obj.b=40
调用change方法后 obj.a=50,obj.b=40
方法重载
在Java程序中,如果同一个类中存在两个方法同名,方法的签名(参数个数、参数类型、类型排列次序)上也一样,将无法编译通过。但在Java中多个方法重名是允许的,只要保证方法签名不同即可,这种特性称为方法重载(overload)。
方法重载需遵循如下两条规则:
- 方法名相同
- 参数列表(个数、类型、顺序)不同;
注意:返回值不影响方法重载。构造方法也可以重载 。
3、包
包中类的访问
一个类可以访问其所在包的所有类。访问其他包的类有如下两种方式访问
//使用import语句导入要访问的类 ,如:
import java.util.*;
import mypackage.school.Student ;
//使用的类名前直接添加完整的包名 ,如:
java.util.Date now = new java.util.Date();
mypackage.school.Student tom = new mypackage.school.Student();
*注意:指明导入当前包的所有类,不能使用类似于java. 的语句来导入以java为前缀的所有包的所有类。
4、访问修饰符
Java中定义了private(私有的)、protected(受保护的)和public(公共的)的访问修饰符,同时也定义了一个缺省的访问级别,用于声明类、属性、方法的访问权限。明确访问修饰符的限制是用好“封装”的关键 :
-
使用public访问修饰符,类的成员可被同一包或不同包中的所有类访问,也就是说,public访问修饰符可以使类的特性公用于任何类;
-
使用protected访问修饰符允许类本身、同一包中的所有类和不同包中的子类访问;
-
如果一个类或类的成员前没有任何访问修饰符时,默认为friendly,它们获得缺省的访问权限,缺省的可以被同一包中的其他类访问;
-
private访问修饰符是限制性最大的一种访问修饰符,被声明为private的成员只能被此类中的其他成员访问,不能在类外看到。
Java中访问控制表
访问控制 | private成员 | 缺省成员 | protected成员 | public成员 |
---|---|---|---|---|
同一类中成员 | Ö | Ö | Ö | Ö |
同一包中其他类 | × | Ö | Ö | Ö |
不同包中子类 | × | × | Ö | Ö |
不同包中非子类 | × | × | × | Ö |
5、静态变量和方法
•静态变量和方法
-
在Java中,可以将一些成员限制为“类相关”的,而前面介绍的成员是“实例相关”的。
-
“实例相关”的成员描述的是单个实例的状态和方法,其使用必须要通过类的实例来完成;
-
“类相关”是在类的成员前面加上“static”关键字,从而直接通过类名就可以访问 。
注意: 类的静态变量和静态方法,在内存中只有一份,供该类的所有对象共用。
public class InstanceCounter {
// 用于统计创建对象的个数
public static int count = 0;
public InstanceCounter() {
count++;
}
// 用于输出count的个数
public static void printCount() {
System.out.println("创建的实例的个数为:" + count);
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
InstanceCounter counter = new InstanceCounter();
}
InstanceCounter.printCount();
}
}
//执行结果如下:
创建的实例的个数为:100
6、类间关系
在面向对象的系统中,通常不会存在孤立的类,类之间、对象之间总是存在各种各样的关系,按照UML(Unified Modeling Language,统一建模语言)规范,类之间存在六种关系:继承 、实现 、依赖 、关联 、聚合 、组成 。
UML的六种关系中,继承和实现是一种纵向的关系,而其余四种是横向关系。其中关联、聚合、组成关系在代码上是无法区分的,更多的是一种语义上的区别。
继承
在Java中,被继承的类叫父类(parent class)或超类(super class),继承父类的类叫子类(subclass)或派生类(derived class)。
在Java中,关键字“extends”表示继承,后面紧跟父类的类名,如下 :
public class Person {
private String name;// 姓名
private int age;// 年龄
private String gender;// 性别
……//省略get和set方法
}
class Teacher extends Person {
private float salary;// 薪酬
private String department;// 部门
……//省略get和set方法
}
class Student extends Person {
private int[] score;// 成绩
private String grade;// 年级
……//省略get和set方法
}
重写
当一个子类继承了一个父类时,可以在子类中直接使用父类的属性和方法。如果父类的方法无法满足子类的需求,则可以在子类中对父类的方法进行改造,也称作重写(override)。重写是Java多态性的另一种体现。
重写的原则
- 重写的方法的签名必须要和被重写的方法的签名完全匹配
- 重写的方法的返回值必须和被重写的方法的返回一致或者是其子类;
- 重写的方法所抛出的异常必须和被重写方法的所抛出的异常一致,或者是其子类;
- 私有方法不能被重写
- 子类重写父类方法的过程中,可访问性只能一样或变的更公开。
public class Base {
public void print() {
System.out.println("In Base ");
}
public static void main(String[] args) {
Son obj = new Son();
obj.print();
}
}
class Son extends Base {
// 覆盖父类的print()方法
public void print() {
System.out.println("In Son ");
}
}
//执行结果如下:
In Son
依赖关系
在一个类的方法中操作另外一个类的对象,则称其依赖于第二个类。
public class Person {
void travel( Car car ) {
car.run("北京");
}
public static void main(String[] args) {
new Person().travel( new Car() );
}
}
class Car {
void run(String city) {
System.out.println("汽车开到" + city);
}
}
关联关系
体现为一个类中使用另一个类的对象作为属性。(子对象)
public class Person {
Car car;
Person(Car car) {
this.car = car;
}
void travel() {
car.run("北京");
}
public static void main(String[] args) {
new Person(new Car()).travel();
}
}
class Car {
void run(String city) {
System.out.println("汽车开到" + city);
}
}
聚合关系
聚合关系体现的是整体与部分的关系,即一个类(整体)由其它类类型的属性(部分)构成。聚合关系中的各个部分可以具有独立的生命周期,部分可以属于多个整体。
public class Department {
Employee[] employees;
public static void main(String[] args) {
Employee e1 = new Employee();
Employee e2 = new Employee();
Employee e3 = new Employee();
Department dept1 = new Department();
dept1.employees = new Employee[] {
e1, e3 };
Department dept2 = new Department();
dept2.employees = new Employee[] {
e2, e3 };
}
}
class Employee {
}
super
“super”关键字代表父类对象。通过使用super关键字,可以访问父类的属性或方法,也可以在子类构造方法中调用父类的构造方法,以便初始化从父类继承的属性。
final
- 用来修饰类、方法和变量,其含义是“不可改变的、最终的” 。
- 修饰类:声明为final的类不能被继承,一个final类中的所有方法都隐式地指定为final。
- 修饰变量:声明为final的变量是一个常量,在定义时必须给予初始值,变量一旦初始化,将不能改变。
- 修饰方法:声明为final的方法不能被子类重写。
7、Object类
概述
Object类是所有类的顶级父类,在Java体系中,所有类都是直接或间接的继承了Object类,Object类包含了所有Java类的公共属性和方法,这些属性和方法在任何类中均可以直接使用,其中较为重要的方法如下表所示:
方法名 | 功能说明 |
---|---|
boolean equals(Object obj) | 比较两个类变量所指向的是否为同一个对象,是则返true |
Class getClass() | 获取当前对象所属类的信息,返回Class对象 |
String toString() | 将调用toString()方法的对象转换成字符串 |
Object clone() | 生成当前对象的一个备份,并返回这个副本 |
int hashCode() | 返回该对象的哈希代码值 |
注意:
- 继承是面向对象编程技术的基础,它允许创建分等级层次的类
- 任何类只能有一个父类,即Java只允许单继承
- 除构造方法,子类继承父类的所有方法和属性
- overload(重载)是多态性的静态展示,override(重写)是多态性的动态展示
- super有两种通用形式:调用父类的构造方法、用来访问被子类的成员覆盖的父类成员
- final修饰符可应用于类、方法和变量
- Object是所有类的最终父类,是Java类结构的基础
- 类之间有依赖、关联、聚合、组成四种关系
结语
如果你觉得这篇文章还可以,别忘记点个赞加个关注再走哦。
如果你不嫌弃,还可以关注微信公众号———梦码城(持续更新中)
梦码在这里感激不敬!!!