JavaOOP---封装/继承

JavaOOP—封装/继承

encapsulation—封装

what?

​ 封装:将类的某些信息【隐藏在类内部】,不允许外部程序【直接访问】,而是通过该类提供的方法来实现对隐藏信息的操作和访问

why?

  1. ​ 良好的封装能够减少耦合(【松耦合】)
  2. ​ 类内部的结构阔以自由修改
  3. ​ 阔以对成员变量进行更精准的控制
  4. ​ 隐藏信息,实现细节
how?

​ 使用private访问修饰符修饰类的属性和方法

​ 两大原则:

  • 1、把属性隐藏起来
  • 2、把尽可能多的东西隐藏起来,对外提供便捷的接口

实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Dog.java

public class Dog {
//隐藏属性
private String name = "无名氏"; //昵称
private int health = 100; //健康值
private int love = 0; //亲密度
private String strain = "拉布拉多"; //品种


//添加属性的getter/setter方法 并加入属性控制语句
//setter:属性赋值:属性的操作(正确判断等)
//getter:属性取值
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getHealth() {
return health;
}

public void setHealth(int health) {
if (health<0 || health>100){
System.out.println("你输入的健康值违规,已默认重置为60");
this.health = 60;
return;
}
this.health = health;
}

public int getLove() {
return love;
}

public void setLove(int love) {
if (love<0 || love>100){
System.out.println("你输入的亲密度值违规,已默认重置为60");
this.love = 60;
return;
}
this.love = love;
}

public String getStrain() {
return strain;
}

public void setStrain(String strain) {
this.strain = strain;
}

public void print(){
System.out.println("我的名字叫做:" + name+ ",健康值为:" +health +",你和我的亲密度为:" + love + ",我的品种为:" + strain
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Penguin.java

public class Penguin {
private String name = "无名氏"; //昵称
private int health = 100; //健康值
private int love = 0; //亲密度
private String gender = "Q仔"; //性别


public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getHealth() {
return health;
}

public void setHealth(int health) {
if (health<0 || health>100){
System.out.println("你输入的健康值违规,已默认重置为60");
this.health = 60;
return;
}
this.health = health;
}

public int getLove() {
return love;
}

public void setLove(int love) {
if (love<0 || love>100){
System.out.println("你输入的亲密度值违规,已默认重置为60");
this.love = 60;
return;
}
this.love = love;
}

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

public void print(){
System.out.println("我的名字叫做:" + name+ ",健康值为:" +health +",你和我的亲密度为:" + love + ",我的性别为:" + gender
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Test.java

import java.util.Scanner;

public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("欢迎光临洋群满满宠物店!");
System.out.print("请输入你想要领养宠物的类型:1:狗狗 2:企鹅 :");
int strain = input.nextInt();
switch (strain){
case 1:
//创建狗狗类的对象
System.out.print("请输入你想要领养狗狗的名字:");
String name = input.next();
System.out.print("请输入你想要领养狗狗的健康值:");
int health = input.nextInt();
System.out.print("请输入你想要领养狗狗的亲密度:");
int love = input.nextInt();
System.out.print("请输入你想要领养狗狗的品种:");
String type = input.next();

Dog dog = new Dog();
//不阔以通过实例点的方式直接赋值,而是调用set方法赋值
//dog.name = name;
dog.setName(name) ;
dog.setHealth(health);
dog.setLove(love);
dog.setStrain(type);

dog.print();
return;
case 2:
//创建企鹅类的对象

System.out.print("请输入你想要领养企鹅的名字:");
String name1 = input.next();
System.out.print("请输入你想要领养企鹅的健康值:");
int health1 = input.nextInt();
System.out.print("请输入你想要领养企鹅的亲密度:");
int love1 = input.nextInt();
System.out.print("请输入你想要领养企鹅的性别:");
String type1 = input.next();

Penguin penguin = new Penguin();
penguin.setName(name1) ;
penguin.setHealth(health1);
penguin.setLove(love1);
penguin.setGender(type1);

penguin.print();
return;
}
}
}

Package—包

what?

​ package是一个为了方便管理组织java文件的目录结构,并防止不同的java文件之间发生命名冲突而存在的一个java特性。不同的package中的类的名称阔以相同,只是在使用时需要带上package的名称加以区分;

why?

​ 防止不同的java文件之间发生命名冲突而存在的一个java特性;

how?

包的命名规范:

  • 1:包名由【小写字母】组成,不能以圆点开头或结尾

    ​ package mypackage;

  • 2:包名之前最好加上唯一的前缀,通常使用组织导致的网络域名(【域名倒置】)

    ​ package.net.javagroup.mypackage;

  • 3:包名后续部分依不同机构内部的活泛不同而不同

    ​ package net.javagroup.reaerch.powerproject;

使用顺序:package(只能有一句)—import(阔以有多句)—class

eg:

JDK提供基本包

  •  java.lang :虚拟机自动引入
    
  •  java.util :提供一些实用类
    
  •  java.io   :输入、输出
    

private/default/protected/public—访问权限控制

修饰符 类包 同包[子类] 异包子类 异包非子类
PRIVATE 关注 关注
DEFAULT 关注
PROTECTED
PUBLIC
1
2
3
4
5
6
7
oop1.Person.java

//无修饰符的类为默认类
class Person {

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
oop1.Student.java

public class Student {
//private修饰的类成员,本类阔以访问
private int age;
//默认修饰符修饰的类成员,本类阔以访问
String name;

//protected修饰的类成员, 本类阔以访问
protected String address;

//public修饰的类成员
public String gender;


public void m1(){
System.out.println(this.age);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
oop1.Test.java

public class Test {
public static void main(String[] args) {
//不同包里面的类既阔以访问pubic修饰的类,也阔以访问默认修饰符修饰的类

Student student = new Student();
//其他类不能调用Student类的private修饰的成员(属性/方法)
//student.age

//默认的修饰符修饰的类属性,不仅本类阔以访问,同包的其他类也阔以访问
System.out.println(student.name);

//protected 修饰符修饰的类属性,本类阔以访问,同包的其他类也阔以访问
System.out.println(student.address);

//public 修饰符修饰的类属性,本类阔以访问,同包的其他类也阔以访问
System.out.println(student.gender);


Person person = new Person();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
oop2.Test.java

public class Test {
public static void main(String[] args) {
//不同包里面的类只阔以访问pubic修饰的类,不阔以访问默认修饰符修饰的类
//Person person = new Person();
Student student = new Student();

//默认修饰符修饰的类成员,不能被其他包访问
//student.name;

//protected 修饰符修饰的类属性,不能被其他包的类访问
//student.address;

//public 修饰符修饰的类属性,能被其他包的类访问
System.out.println(student.gender);

}
}

Static—静态

what?

​ 在java程序中static修饰的任何变量都是在编译时有系统【自动分配内存来储存】的,而所谓的静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间;

why?

​ 优点:

​ 当一个方法或者变量需要初始化加载,或者【经常被调用】的时候阔以加上static;因为用static修饰的方法阔以直接使用类名直接调用,不一定需要县实例化对 象,很大程度上简化了开发;

​ 缺点:

​ 初始化加载,比较占内存,所以【不经常使用】的方法,不建议加static

how?
static修饰的变量:
1
2
3
4
5
6
7
8
9
Person.java

public class Person {
//属性,成员变量,全局变量---实例变量
String name;
int age;
//静态变量
static char gender;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Test.java

/**
* static阔以用来修饰
* 1、成员变量 :静态变量,阔以直接通过类名访问
* 2、成员方法 :静态方法,阔以直接通过类名访问
* 3、代码块 :静态代码块,当java虚拟机加载时,就会执行该代码块
*
*
* 类的成员变量包括
* 1、类变量(静态变量)
* 1.1、被static修饰的变量
* 1.2、在内存中只有一个拷贝
* 1.3、类内部, 可在任何方法中直接访问静态变量
* 1.4、其他类中,阔以直接通过类名访问
* 2、实例变量
* 2.1、没有被static修饰的变量
* 2.2、没创建一个实例,就会为实例变量分配一次内存,实例变量阔以在内存中有多个拷贝,互不影响
*
*
* static变量的作用
* 1、能被类的所有实例共享,可作为实例之间进行交流的共享数据
* 2、如果类的所有实例都包括一个相同的常量属性,阔以把这个属性定义为静态常量类型,从而节省内存空间
*
*
*static变量
* 1、类变量
* 2、在内存中只有一个【拷贝】
* 3、类内部,可在任何方法内直接访问【静态变量】
* 4、其他类中, 阔以直接通过【类名】访问类成员的访问控制
* 5、能被类的【所有实例共享】,可作为实例之间进行交流的共享数据
*
*/
public class Test {

public static void main(String[] args) {
//实例化对象
Person p = new Person();

p.age = 16;
p.name = "洋群满满";
p.gender = '男';
//static修饰的属相直接:类名.属性 即可赋值
Person.gender = '男';
}
}
static修饰的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Person.java

public class Person {
//属性,成员变量,全局变量---实例变量
String name;
int age;
//静态变量
static char gender;

//成员方法:实例方法---阔以调用实例变量、实例方法、静态变量、静态方法
public void m1(){
//实例方法中阔以【访问静态变量】,但是【不能定义静态变量】
//static int age;
System.out.println(this.age);
System.out.println(gender);
m2();
m3(); //斜体代表静态方法
}

public void m2(){
System.out.println("实例方法m2");
}
//静态方法
public static void m3(){
//在静态方法中不能使用this
//System.out.println(this.age);

//在静态方法中不能调用实例方法
//m1();

//在静态方法中不能调用实例变量---别static修饰的方法,不能调用没有被static修饰的属性
//System.out.println(age);

//在静态方法中阔以访问静态变量
System.out.println(gender);

//在静态方法中阔以访问静态方法
Person.m4();
System.out.println("静态方法m3");
}


public static void m4(){
System.out.println("静态方法m4");

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Test.java

/**
* static阔以用来修饰
* 1、成员变量 :静态变量,阔以直接通过类名访问
* 2、成员方法 :静态方法,阔以直接通过类名访问
* 3、代码块 :静态代码块,当java虚拟机加载时,就会执行该代码块
*
* 静态方法:阔以直接通过类名访问
* 1、静态方法中不能使用this和super
* 2、不能直接访问所属类的实例变量和实例方法
* 3、阔以直接访问类的静态变量和静态方法
* 实例方法:通过实例访问
* 1、阔以直接范文所属类的静态变量、静态方法、实例变量、实例方法
* 静态方法必须被实现-------对于抽象方法/抽象类来说的
*
*
* main()就是最常用个静态方法
*
*/
public class Test {
public static void main(String[] args) {
//调用类的普通成员变量(属性),创建对象(实例),通过对象去访问------》实例变量
Person p = new Person();
p.age = 16;
p.name = "洋群满满";
//静态变量---》类名去调用
Person.gender = '男';


//通过实例调用实例方法
p.m1();

//通过类名调用静态方法
Person.m3();

//回想以前的Math的静态方法
Math.random();
}
}
static 修饰的代码块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Test.java

/**
* static阔以用来修饰
* 1、成员变量 :静态变量,阔以直接通过类名访问
* 2、成员方法 :静态方法,阔以直接通过类名访问
* 3、代码块 :静态代码块,当java虚拟机加载时,就会执行该代码块
*
* JVM加载类的时候,加载静态代码块
* 1、当java虚拟机加载类时,就会执行该代码块
* 2、如果有多个静态块,按【顺序加载】
* 3、每个静态代码块只会被【执行一次】
*
*
*/


public class Test {
static int num = 100;

static {
num += 100;
System.out.println(num);
}

static {
num += 100;
System.out.println(num);
}


public static void main(String[] args) {
//因为每个静态代码块只会被执行一次,所以t2的num不会被重新赋值
Test t1 = new Test();
Test t2 = new Test();

System.out.println(Test.num);
}
}

Extends—继承

what?

​ 继承是面向对象重要的基石,原因他允许创建分等级层次的类;

why?

​ 提高代码的【复用性】;

how?
普通的父子类继承代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
Dog.java

public class Dog extends Pet{
private String strain = "拉布拉多";

public String getStrain() {
return strain;
}

public void setStrain(String strain) {
this.strain = strain;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Penguin.java


public class Penguin extends Pet{
private String gender = "Q仔"; //性别

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Pet.java

//父类:提取共性代码
public class Pet {
private String name; //昵称
private int health; //健康值
private int love; //亲密度

public Pet() {
}

public Pet(String name, int health, int love){
this.name = name;
this.health = health;
this.love = love;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getHealth() {
return health;
}

public void setHealth(int health) {
this.health = health;
}

public int getLove() {
return love;
}

public void setLove(int love) {
this.love = love;
}



public void print(){
System.out.println("我的名字叫做:" + name+ ",健康值为:" +health +",你和我的亲密度为:" + love
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Test.java

import java.util.Scanner;
/**
* 何时使用继承:
* 1符合is-a关系的设计使用继承
* 2、将子类共有的属性和行为方法父类中
* 3、Java只支持单根继承,即一个类只能有一个直接的父类
*
*/

public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("欢迎光临洋群满满宠物店!");
System.out.print("请输入你想要领养宠物的类型:1:狗狗 2:企鹅 :");
int strain = input.nextInt();
switch (strain){
case 1:
//创建狗狗类的对象
System.out.print("请输入你想要领养狗狗的名字:");
String name = input.next();
System.out.print("请输入你想要领养狗狗的健康值:");
int health = input.nextInt();
System.out.print("请输入你想要领养狗狗的亲密度:");
int love = input.nextInt();
System.out.print("请输入你想要领养狗狗的品种:");
String type = input.next();

Dog dog = new Dog();
dog.setName(name) ;
dog.setHealth(health);
dog.setLove(love);
dog.setStrain(type);

dog.print();
return;
case 2:
//创建企鹅类的对象

System.out.print("请输入你想要领养企鹅的名字:");
String name1 = input.next();
System.out.print("请输入你想要领养企鹅的健康值:");
int health1 = input.nextInt();
System.out.print("请输入你想要领养企鹅的亲密度:");
int love1 = input.nextInt();
System.out.print("请输入你想要领养企鹅的性别:");
String type1 = input.next();

Penguin penguin = new Penguin();
penguin.setName(name1) ;
penguin.setHealth(health1);
penguin.setLove(love1);
penguin.setGender(type1);

penguin.print();
return;
}
}
}
使用修饰控制访问权限的父子类继承代码如下:
1
2
3
4
5
6
7
8
9
10
oop1.Person.java

//父类
public class Person {
private int age;
protected String name;
char gender;
public String address;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
oop1.Student.java

/**
* 子类能继承父类什么?
* 1、继承public修饰的属性和方法,不管同包子类还是异包子类
* 2、继承protected修饰的属性和方法,不管同包子类还是异包子类
* 3、继承默认权限修饰符修饰的属性和方法,但是子类和父类必须同一个包中
*
*
* 子类不能继承父类什么?
* 1、不能继承父类中private修饰符修饰的属性和方法
* 2、不能继承子类与父类不在同一包中父类中默认权限修饰符修饰的属性和方法
* 3、不能继承父类的构造方法,但是【阔以调用】
*
*/


public class Student extends Person {

public void m1(){
//子类阔以继承父类的protected修饰的成员,不同包也阔以
System.out.println(name);
//子类无法继承父类的private成员
//System.out.println(age);
System.out.println(address);
System.out.println(gender);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
oop2.Teacher.java

public class Teacher extends Person {
public void m1(){
//子类阔以继承父类的protected修饰的成员,【不同包也阔以】
System.out.println(name);
//子类【无法继承父类的private】成员
//System.out.println(age);
System.out.println(address);
//同包的子类库阔以继承父类的默认修饰符修饰的成员,但是【不同包的不阔以】
//System.out.println(gender);
}

}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!