Java的类封装及封装关键字(this、static),类的使用
一、封装的基本概念
1.将东西打包在一起,然后以新的方式呈现出来(比如将方法和字段一起包装在一个单元中,这个单元以类的形式呈现出来)。
2.信息隐藏,隐藏对象的实现细节,不让外部直接访问到。
3.将数据和方法包装进类中,加上具体实现的隐藏(访问修饰符),共同被称作封装,其结果是一个同时带有特征和行为的数据类型。
从以上我们可以得知:定义类,定义其属性,方法的过程称为封装类
封装的优点:
- 良好的封装能够减少耦合。
- 类内部的结构可以自由修改。
- 可以对成员变量进行更精确的控制。
- 隐藏信息,实现细节。
二、类的创建及使用
(一).类的创建:
- 创建类需要用 class关键字
class 类名称
{
属性
方法
}
- 类的访问修饰符:在我们的代码中有许多类或者方法和变量不希望别人有太高的权限访问,此时可以用访问修饰符把他隐藏起来。
public: 该类或非该类均可以访问
private: 只有该类可以访问
protected: 该类及其子类的成员可以访问,同一个包中的类也可访问
默认: 同一个包中的类可以访问
- 属性封装的实现(基于private):
修改属性的可见性来限制对属性的访问
为每个属性创造一个赋值方法和取值方法,对于公开这些方法属性的访问中,根据需要加入相应操作
class Student
{
private int score;//只有该类可以访问该变量
public void setter(int score){ //赋值方法
this.score = score; //this.score是此类中定义的score,右边的是形参
}
public int getter(){
return score-20;
}
}
public class Test {
public static void main(String[] args) {
Student stu = new Student();
stu.setter(100);
System.out.println(stu.getter());
}
}
以上的方法这样可以通过公开的方法(sette),(getger)来对类中的私有权限变量(score)进行读写。其他类不能直接对score直接进行访问。
- 方法封装的目的:
隐藏方法的实现细节(方法体),向外部提供公开接口(方法头),以供安全调用简化使用,方便修改维护。根据需要可以私有化方法,供内部使用。
class Student
{
private int score;//只有该类可以访问该变量
private void sco(int score){
this.score = score-100; //this语法可见下文
}
public int myscore(int score){
sco(score);
return this.score;
}
}
public class Test {
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu.myscore(1000));
}
}
以上的sco是私有化的方法,其他类不可访问,调用公有化的mysocre,方法中调用私有化的方法sco,实现对私有化score变量的修改。
- 类的构造方法
- 构造方法负责初始化对象,为对象的属性赋合适的初值
- 创建对象时,其类的构造方法确保在用户操作对象之前,系统保证初始化的进行
- 构造方法名与类名一致,没有返回类型(不同于void类型返回值,void是没有具体返回值类型;构造函数是连类型都没有),方式实现主要为字段赋初值。一个类可以有多个构造方法(方法可重载,函数名一样,参数列表不同 )
- 构造方法的调用在实例化时用new+构造方法自动调用,具体调用哪个构造方法根据传递参数自动选择,如果类中没有主动创建构造方法则在实例化时系统会自动创建一个无参数无实现的构造方法。
class Student
{
int score;
String sex;
int age;
Student(){
System.out.println("构造1被调用");
}
Student(int score,String sex,int age){
System.out.println("构造2被调用");
this.score = 0;
this.sex = "男";
this.age = 10;
System.out.println(this.score+this.sex+this.age);
}
Student(int score,int age,String sex){
System.out.println("构造3被调用");
this.score = 0;
this.sex = "女";
this.age = 18;
System.out.println(this.score+this.sex+this.age);
}
}
public class Test {
public static void main(String[] args) {
Student stu1 = new Student();
Student stu2 = new Student(80,"实参",80);
Student stu3 = new Student(80,80,"实参");
}
}
结果如下:
构造1被调用
构造2被调用
0男10
构造3被调用
0女18
以上new传递的实参只是为了区分构造方法,并没有对实参或类的变量和方法做任何实现,如有需要可以在构造方法中做具体初始化。
- this关键字
- ①在类的方法中,使用this关键字代表的时调用此方法的对象的引用
(可以理解为this.score就是类中的变量score,所以可以实现形参名和类中的变量名相同,以下为了方便理解所以设置形参名和变量名不同,有兴趣可以修改形参名观察结果)
class Student
{
int score;
String sex;
int age;
Student(int newscore,int newage,String newsex){
score = newscore;//构造方法根据传上来的参数对score初始化
this.score = this.score -10;
}
void test(){
System.out.println(score);
}
}
public class Test {
public static void main(String[] args) {
Student stu = new Student(100,18,"男");
stu.test();
}
}
结果为:
90
- ②this可以看作是一个变量,它的值是当前对象的引用
class Student
{
int score;
String sex;
int age;
Student(int newscore){
score = newscore;
}
void test(){
Student stu2 = null;
stu2 = this;//这里的this相当于stu这个对象,把stu赋值给stu2
System.out.println(stu2.score);
}
}
public class Test {
public static void main(String[] args) {
Student stu = new Student(100);
stu.test();
}
}
- ③在类的构造方法中可以调用this([参数列表])来调用该类的指定构造方法
注意,调用指定构造方法时该指令必须在调用方法的第一句
class Student
{
int score;
String sex;
int age;
Student(int newscore){
System.out.println("构造1调用");
this.score = newscore;
System.out.println(score);
score = newscore;
}
Student(int newscore,int age){
this((newscore));//调用指定构造方法必须在第一句,如果在下面则会报错
System.out.println("构造2调用");
this.score = 500;
System.out.println(score);
}
}
public class Test {
public static void main(String[] args) {
Student stu = new Student(100,19);
}
}
输出为:
构造1调用
100
构造2调用
500
- static关键字
- 用来修饰类的成员—修饰成员变量的称为类变量(静态变量)
- 修饰成员方法称之为类方法(静态方法)
- 当类被加载时就会被加载,优先于对象的存在
- 用来修是语句块称为静态代码块,优先于构造方法之前执行,只会执行一次,用来对静态代码块初始化(静态代码块只能初始化静态的变量)
- 调用的时候可以直接通过类名.成员访问
- 注意点1:静态方法只能访问外部静态成员
- 注意点2:静态方法不能出现this关键字
当修饰类变量时(静态变量)
class Student
{
static int score;
}
public class Test {
public static void main(String[] args) {
Student.score = 10;
Student stu1 = new Student();
Student stu2 = new Student();
System.out.println(stu1.score);
System.out.println(stu2.score);
stu1.score = 20;
System.out.println(stu1.score);
System.out.println(stu2.score);
}
}
输出结果为
10
10
20
20
由此可知静态变量可以不通过实例化直接访问,并且当stu1修改了静态变量,stu2也会随之改变
当修饰类方法时(静态方法)
public class Test {
public static void main(String[] args) {
System.out.println(add(10,20));
}
static int add(int a,int b){
return a+b;
}
}
加上static可以不用实例化直接访问,如果没加则必须实例化,否则出错
当修饰静态代码块时
class Student
{
int score;
String sex;
int age;
static int data;
static{
System.out.println("静态代码块");
}
Student(int newscore,int age){
System.out.println("构造2调用");
}
}
public class Test {
public static void main(String[] args) {
Student stu = new Student(100,19);
Student stu2 = new Student(100,19);
}
}
结果为
静态代码块
构造2调用
构造2调用
我们new了两个对象,而静态代码快就被执行了一次,由此可知静态代码块只执行一次,并且在构造之前被执行
三、类的使用
使用类需要注意以下几点:
- 类中的方法可以直接访问类中的变量,不需要传参。
- 类相当于一个模板,要使用他必须实例化一个对象,实例化的内存划分如下图
例如有个Student的类:
Student stu1 = new Student();
以上左边的Student是类名,stu1为实例化的对象名,new是实例化(创建对象)的关键字,后面跟的Student()为构造方法,一个类可以有多种构造方法,根据不同的构造方法决定创建对象时是否需要传参。
四、包
- 一个类可以使用同一个包中的所有类
- 一个类可以使用其他包中所有公开类
怎么使用其他包中的公开类
- 在每个类签名加上完整包名,例如
java.util.Data today = new java.util.Data(); - 更简洁的方式,使用import语句来导用包(eclipse ctrl+shift+o)
import java.util.Data;
引用就可以用Data today = new Data();