封装的概念
封装是面向对象的三大特征之一。
面向对象的三大特征是:封装、继承、多态。
类 = 属性 + 方法,类是对属性和方法的封装。类封装了类的成员。
结合Student类,介绍后续内容:
如果在类的外部可以随意访问类的成员,那将属性和方法放到类中就没有意义了。因此Java允许在类中通过访问修饰符控制类成员的访问权限。之前已经接触过public访问修饰符。
访问控制
在完整学习访问控制之前,先熟悉一下包的概念。
包与访问范围
(1)包的概念
类通常位于某个包中,包(packages)是多个类的容器。它们用于保持类的名称空间相互隔离。因此包是一种名称机制。
例如,Java类库中的类,分别包含在不同的包中:java.lang;java.util。例如String类位于java.langl包中。
(2)定义包
package pack1
(3)层次化的包
package com.xszx.sjt2111
(4)包与目录结构
位于包中的类,在文件系统中也必须有与包名层次相同的目录结构。
需要指出的是,包名与文件目录结构一致是针对.class文件而言的,对于源代码文件没有这一要求,但是通常也将源代码文件放到与包名一致的目录结构中。并且建议将源文件与类文件分开存放。
(5)导入包
类的全名为:包名.类名。例如在com.xszx包中定义的Student类,其全面为com.xszx.Student。
当在不同的包中使用某个类时,需要使用类的全名,如果包名很长的话,使用类的全名不是很方便,这时可以通过导入包来避免使用类的全名。
导入包的目的:减少输入
导入包的两种方式
import java.util.Scanner;
import java.util.*;
包既是一种命名机制,也是一种可见性控制机制。可以在包中定义该包外部的代码不能访问的类成员。
访问修饰符与访问范围
类是对类成员(属性和方法)的封装,可以通过不同的访问修饰符控制类成员的可见范围,即控制类的成员在多大的范围是可见的。
类成员的访问范围划分为四个:本类、本包、子类、全局(所有包)
为类的成员指定不同的修饰符,就是控制成员的在什么样的范围内是可见的,即在什么样的范围是能够访问的。
private | 默认 | protected | public | |
同一个类中 | 是 | 是 | 是 | 是 |
相同包中的其他类 | 否 | 是 | 是 | 是 |
子类(不同包、相同包) | 否 | 否 | 是 | 是 |
全局(所有包) | 否 | 否 | 否 | 是 |
访问范围: 本类 < 本包 < 子类 < 全局(所有包)
访问修饰符:private < 缺省(default) < protected < public
封装的通常做法:
(1)将类的属性的访问权限设置为private,提供访问权限为public的set和get方法。在有些情况下不提供set和get方法,有时只提供其中的一个。
(2)提供合理的构造方法,即开发相应参数的构造方法,方便实例化对象。
(3)类的全部或部分方法的访问权限为public,类的公有方法是类对外开放的接口,供外部代码使用类的功能。类的私有方法通常是辅助方法实现部分功能,供类的公有方法调用。
封装案例:
在p1包中定义Student类
在p1包中定义StudentTest类,使用Student类,访问该类中的成员变量和方法。
将StudentTest类的定义放入到p2包中,再次访问类中的成员变量和方法。
方法重载
方法重载基础
直接切入主题:
在类中可以定义名称相同的方法:只要形参列表不同即可。
特点:
1、方法名相同
2、形参列表不同:形参的类型/顺序、形参的个数
注意的地方:
1、返回值在区分重载方法时不起作用。修饰符也不起作用
2、当调用重载方法时,Java使用参数的类型和/或数量确定实际调用哪个版本。
方法重载案例:
Calculator类,添加add()方法,计算两个数的和。int float double
重载构造方法
Box(double length, double width, double height)
Box(double dim)
Box(Box box)
Box()
特别说明:
在某个构造方法中可以使用this()调用重载的构造方法:
public Box(double dim){
this(dim, dim, dim)
}
this关键字
在类的内部,可以在任何方法中使用this引用当前对象。
使用this关键字解决在实例变量和局部变量之间可能发生的任何名称冲突。
局部变量,包括方法的形参,可以和类的实例变量重名。当局部变量和实例变量具有相同的名称时,局部变量隐藏了实例变量。
static关键字
在正常情况下,只有通过组合类的对象才能访问该类的成员。有时可能希望定义能够独立于类的所有对象进行使用的成员。为了创建这种成员,需要在成员声明的前面使用关键字static。例如Math类中的方法,就是静态方法。
方法和变量都可以声明为静态的。main()方法是最常见的静态成员的例子。main()方法被声明为静态的,因为需要在创建所有对象之前调用该方法。
静态变量
案例:(演示静态变量的访问方式、不同实例共享相同的值)
Math中的成员变量PI就是静态变量。
public class StaticM{
//实例变量
private int i;
//静态变量
static int si;
public static showStatic(){};
}
特别注意:
(1)被声明为静态的变量本质上是全局变量,类的所有实例共享相同的静态变量。因此,通过一个对象修改静态变量的值后,通过该类的其他对象访问到的静态变量是修改后的值。
(2)访问静态变量的方式:
类名.变量名(推荐)
对象.变量名(不推荐)
(3)初始化时机
静态变量:当类被虚拟机加载,静态变量就初始化,既不需要创建类的对象就可以使用静态变量。
实例变量:创建类的对象时初始化
静态代码块
静态代码块,只执行一次,而且是类加载时就执行
作用:一般完成静态变量初始化赋值或完成整个系统只执行一次的任务
静态方法
最典型的静态方法是main()方法;
静态的方法有几个限制:
它们只能直接调用其他静态方法。
它们只能直接访问静态数据
它们不能以任何方式引用this或super关键字。
案例:
改写前面的Calculator类,使用静态方法实现两个数量相加的功能。
main方法、math类中提供的许多方法都是静态方法
关于static的几点说明
1、static的本质作用是区分成员属于类还是属于实例。
2、通常把使用static修饰的变量和方法称为类变量和类方法,有时也称为静态变量和静态方法,把不使用static修饰的变量和方法称为实例变量和实例方法。
3、对于使用static修饰的成员,既可以通过类来调用也可以通过类的实例调用,但是建议使用类调用静态成员。对于实例变量和实例方法,则只能通过类的实例调用。