封装
将某些属性和实现细节隐藏在类内部,不允许外部程序直接访问,要访问该类的隐藏数据,必须通过指定的方式进行。
将不需要对外提供的内容隐藏,提供公共方法对其进行访问。
- 通过使用
private
对属性进行私有化; public
set 变量名()方法,对属性进行赋值;public
get 变量名()方法,用于获取属性的值;
定义Person类
public class Person {
// 定义私有属性
private String name;
private int age;
// 定义构造方法
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
// 定义setter和getter
public void setName(String name) {
if (!name.isEmpty()) {
this.name = name;
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0) {
this.age = age;
} else {
this.age = 18;
}
}
// 定义showMe方法
public void show() {
System.out.println("我是" + name + ",今年" + age + "岁了。");
}
}
定义测试类
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person("laobai", 18);
p1.show();
p1.setName("AILynn");
p1.setAge(-1);
p1.show();
}
}
执行结果:
我是laobai,今年18岁了。
我是AILynn,今年18岁了。
访问权限
访问范围 | public | protected | default | private |
---|---|---|---|---|
同一个类中 | ✅ | ✅ | ✅ | ✅ |
同一个包中 | ✅ | ✅ | ✅ | ❌ |
子类 | ✅ | ✅ | ❌ | ❌ |
不同包中 | ✅ | ❌ | ❌ | ❌ |
static关键字
由static
修饰的变量,被称为静态变量,也叫类变量;由static
修饰的方法,被称为静态方法,也叫类方法。可以通过类名.变量名
和类名.方法名
来访问。
继承
子类继承父类的属性和行为,使得子类对象可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类的非私有的属性和行为。
以上面封装中的Person类为父类,写Student子类继承Person类
public class Student extends Person{
}
Student类使用extends
关键字继承了Person类,没有写其他代码,但已经拥有了Person类的属性和方法。
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("小明");
s1.setAge(12);
s1.showMe();
}
}
执行结果:
我是小明,今年12岁了。
在Student类中增加身高属性,并重写父类的show()方法
package test02;
public class Student extends Person {
private int height; // 身高厘米,只要整数部分
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public void show() {
super.show();
System.out.println("我在的身高是:" + height + "cm");
}
}
修改StudentTest.java
package test02;
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("小明");
s1.setAge(18);
s1.show();
s1.setHeight(175);
s1.show();
}
}
执行结果:
我是小明,今年18岁了。
我在的身高是:0cm
我是小明,今年18岁了。
我在的身高是:175cm
通过super
关键字调用父类的属性和方法。super
必须写在方法的第一行。
方法重写与方法重载:
- 方法重写,发生在子类和父类之间,子类和父类的方法完全相同,方法名、返回值类型、参数列表均形同;
- 方法重载,发生在同一个类中,或子类中,方法名相同,参数不同,参数个数不同,或参数类型不同。
方法重写可以使用@Override
注解来修饰
@Override
public void show() {
super.show();
System.out.println("我的身高是:" + height + "cm");
}
final
修饰变量为常量;修饰方法,方法无法被重写;修饰类,类不能被继承。
多态
多态是指同一个行为可以有多个不同表现形式。也就是在父类中定义的属性和方法,在子类继承后,可以有不同的数据类型或表现不同的行为。这可以使得同一个属性和方法,在父类及其各个子类中,可能有不同的表现或含义。
多态分为编译时多态和运行时多态。编译时多态主要是通过方法重载overload来实现;运行时多态主要通过方法的重写override来实现。编译时取决于父类,运行时取决于子类。
新建教师类,私有属性工龄seniority
package test02;
public class Teacher extends Person {
private int seniority; // 工龄
public int getSeniority() {
return seniority;
}
public void setSeniority(int seniority) {
this.seniority = seniority;
}
@Override
public void show() {
super.show();
System.out.println("我的工龄是" + seniority + "年.");
}
}
测试类
package test02;
public class Test {
public static void main(String[] args) {
// 向上转型
Person stu1 = new Student();
Person tea1 = new Teacher();
Person per1 = new Person();
stu1.setName("AILynn");
stu1.setAge(16);
stu1.show();
tea1.setName("PLScript");
tea1.setAge(26);
tea1.show();
per1.setName("Laobai");
per1.setAge(28);
per1.show();
System.out.println("--------------------");
// 向下转型
Student stu2 = (Student)stu1;
stu2.setHeight(175);
stu2.show();
Teacher tea2 = (Teacher)tea1;
tea2.setSeniority(20);
tea2.show();
}
}
执行结果:
我是AILynn,今年16岁了。
我的身高是:0cm
我是PLScript,今年26岁了。
我的工龄是0年.
我是Laobai,今年28岁了。
--------------------
我是AILynn,今年16岁了。
我的身高是:175cm
我是PLScript,今年26岁了。
我的工龄是20年.
抽象类
抽象类是一种不能被实例化的类,其目的是为了被其他类继承并实现其抽象方法。抽象方法是一种没有实现的方法,只有定义,需要在子类中被实现。抽象类可以包含非抽象方法和属性,但至少要有一个抽象方法。抽象类使用abstract
关键字修饰,而抽象方法同样使用abstract
关键字来修饰。
- 抽象类不能被实例化,只能被继承;
- 抽象类可以包含抽象方法和非抽象方法;
- 抽象方法只有声明,没有实现;
- 抽象方法必须被子类实现;
- 抽象类可以被用来定义一些通用的方法和属性,让子类继承并实现;
新建人类抽象类
public abstract class Person {
// 有抽象方法的类,必须是抽象类;
// 抽象类中可以没有抽象方法
// 抽象类不能实例化对象,必须被子类继承
public abstract void eat();
public void drink(){
System.out.println("喝水");
}
}
工人类并实现抽象方法
import test03.Person;
// 子类继承抽象类之后,必须要重写父类的抽象方法 或 子类也是抽象类,由子类的子类重写抽象方法
public class Worker extends Person {
@Override
public void eat() {
System.out.println("一日三餐");
}
}
测试类
public class TestWorker {
public static void main(String[] args) {
Worker worker1 = new Worker();
worker1.eat();
}
}
接口
接口在java中是一个抽象类型,是抽象方法的集合。接口以interface
来声明,一个类通过继承接口的方式从而来继承接口的抽象方法。接口并不是类,类描述对象的属性和方法。接口则包含类要实现的方法。接口无法被实例化,但可以被实现。一个实现接口的类,必须实现接口内所有的抽象方法,否则就必须声明为抽象类。一个类可以实现2个接口,也可以继承和实现接口同时使用。
新建一个人类的接口
package test04;
public interface Person {
// 抽象方法
// 默认添加public abstract修饰符
void eat();
void talk();
// 静态常量,不推荐使用
// 默认添加public static final修饰符
String name = null;
// 默认方法
// 子类可以直接使用默认方法,也可以根据需要重写默认方法。
default void breathe(){
System.out.println("呼吸新鲜空气!");
}
// 静态方法
// 不能被继承,通过接口名调用。
static void declaration(){
System.out.println("生而无畏,战至终章!");
}
}
另写一个语言的接口
package test04;
public interface Language {
void foreign();
}
写个工人类实现上面两个接口
package test04;
// 非抽象类实现接口,必须重写所有的抽象方法
public class Worker implements Person, Language{
@Override
public void eat() {
System.out.println("一日三餐");
}
@Override
public void talk() {
System.out.println("谈笑风生");
}
@Override
public void foreign() {
System.out.println("Speaking English");
}
}
测试类
package test04;
public class Test {
public static void main(String[] args) {
Worker worker1 = new Worker();
worker1.eat();
worker1.talk();
worker1.breathe();
Person.declaration();
worker1.foreign();
}
}
执行结果:
一日三餐
谈笑风生
呼吸新鲜空气!
生而无畏,战至终章!
Speaking English
内部类
在一个类的内部定义一个内部类
public class Apple { // 外部类 Apple
private String brand = "Apple"; // 品牌名苹果
// 成员内部类
// 内部类可以直接访问外部类的成员,包括私有成员
// 外部类访问内部类成员,必须创建内部类对象
// 外部类内部,实例化内部类: 内部类 对象变量名 = new 内部类()
// 外部类外部,实例化内部类:外部类.内部类 对象变量名 = new 外部类().new 内部类
class Phone{
private String model = "iphone 15"; // 型号
public void show(){
System.out.println("品牌是:" + brand);
}
}
public void produce() {
// 若要访问内部类,需定义成员内部类对象
Phone phone = new Phone();
System.out.println(phone.model);
phone.show();
}
}
测试内部类
public class AppleTest {
public static void main(String[] args) {
Apple apple = new Apple();
apple.produce();
Apple.Phone phone = new Apple().new Phone();
phone.show();
}
}
执行结果:
iphone 15
品牌是:Apple
品牌是:Apple
成员内部类
- 内部类可以直接访问外部类的成员,包括私有成员
- 外部类访问内部类成员,必须创建内部类对象
- 外部类内部,实例化内部类: 内部类 对象变量名 = new 内部类()
- 外部类外部,实例化内部类:外部类.内部类 对象变量名 = new 外部类().new 内部类
静态内部类:
- 静态内部类,不能直接访问外部类的非静态成员;
- 静态内部类,可以直接范围外部类的静态成员;
- 外部类的内部,访问静态内部类中的静态成员:静态类名.静态成员;
- 外部类的外部,访问静态内部类中的静态成员:外部类名.静态类名.静态成员;
- 外部类的内部,实例化静态内部类:内部类 对象名 = new 内部类();
- 外部类的外部,实例化静态内部类:外部类.内部类 对象名 = new 外部类.内部类();
- 访问内部类的非静态成员,先实例化静态内部类,通过对象访问。