Java面向对象的三大特性:封装、继承、多态。
一、封装:封装就是将数据和行为组合到一个类中,这个类就是一个对象,并对被封装的数据作出保护处理,也就是私有化,然后对外提供这些数据的访问方法(getter和setter方法),这些数据只能通过getter和setter方法进行访问,我们就可以通过这两个方法对数据进行保护,例如:对一些只能读取不能修改的数据,我们就可以只提供getter方法。应用封装可以提高代码的可靠性。最常见的封装,po类:
public class Encapsulation {
private String variable; //私有化
public String getVariable() { //提供getter方法,用来获取属性数据
return variable;
}
public void setVariable(String variable) { //提供setter方法,用来修改属性
this.variable = variable;
}
}
1.1 this关键字:在封装对象的时候经常会用到this关键字。
this指代的对象:
普通方法中:this指向调用该方法的对象
构造方法中:this指向正要修改的对象
1.2 内部类:
内部类可以直接访问外部类的属性和方法,但外部类不能直接访问内部类的属性;
内部类只能通过外部类进行访问,提高了安全性。
1.2.1 成员内部类:
内部类直接访问外部类的属性和方法:
public class OutClass {
private String a = "外部类的属性";
public void outRun() {
System.out.println("外部类方法");
}
//成员内部类
public class InClass{
public void inRun() {
System.out.println(a); //直接访问外部类属性
outRun(); //直接访问外部类方法
}
}
@Test
public void run() {
new OutClass().new InClass().inRun(); //使用内部类方法
}
}
运行结果:
外部类的属性
外部类方法
外部类访问内部类的属性和方法:
public class OutClass {
public void outRun() {
InClass inClass = new InClass();
System.out.println(inClass.b); //通过内部类对象访问内部类属性
inClass.inRun(); //通过内部类对象访问内部类方法
}
//成员内部类
public class InClass{
private String b = "内部类属性";
public void inRun() {
System.out.println("内部类方法");
}
}
@Test
public void run() {
new OutClass().outRun(); //使用外部类方法
}
}
运行结果:
内部类属性
内部类方法
通过这两个测试可以看到,内部类能够直接访问外部类的属性和方法,而外部类只能通过内部类对象访问内部类的属性和方法。
1.2.2 静态内部类:
因为静态内部类是静态的,不能直接访问外部类的非静态的属性和方法,可以通过外部类对象访问;
在创建静态的内部类对象时,不需要通过外部类对象。
public class OutClass {
private String outA = "外部类非静态属性";
private static String outB = "外部类静态属性";
public void outRun() {
System.out.println("外部类非静态方法");
}
public static void outStaticRun() {
System.out.println("外部类静态方法");
}
//静态内部类
public static class InClass{
public void inRun() {
System.out.println(outB); //直接访问外部类的静态属性
outStaticRun(); //直接访问外部类的静态方法
System.out.println(new OutClass().outA); //通过外部类对象访问外部类属性
new OutClass().outRun(); //通过外部类对象访问外部类方法
}
}
@Test
public void run() {
new InClass().inRun(); //使用静态内部类方法,不需要外部类对象,可以直接创建内部类对象
}
}
运行结果:
外部类静态属性
外部类静态方法
外部类非静态属性
外部类非静态方法
可以看到,静态内部类可以直接访问外部类的静态成员,而想要访问非静态成员,就需要创建外部类对象来调用。
1.2.3 方法内部类:
方法内部类就是定义在外部类的方法内部的类,这个类只能在的这个方法中使用;
方法内部类不能使用访问修饰符和静态修饰符。
public class OutClass {
//外部类方法
public void outRun() {
//方法内部类
class InClass{ //注意:这里不能使用public、protected、default、private访问修饰符
// 和static静态修饰符
private String a = "方法内部类的属性";
public void inRun() {
System.out.println("方法内部类的方法");
}
}
InClass inClass = new InClass(); //创建方法内部类对象
System.out.println(inClass.a); //通过对象使用方法内部类属性
inClass.inRun(); //通过对象使用方法内部类方法
}
@Test
public void run() {
//调用外部类方法
new OutClass().outRun();
}
}
运行结果:
方法内部类的属性
方法内部类的方法
二、继承:
继承可以说是对方法的抽象,将一批方法的公有属性抽象出来,这样可以提高代码的复用性;
继承只能单继承,子类继承父类,可以获得父类的所有属性和方法,但是私有属性不能直接访问。
//父类
public class Father {
private String privateStr = "父类的私有属性";
public String publicStr = "父类的公有属性";
public String getPrivateStr() {
return privateStr;
}
public void setPrivateStr(String privateStr) {
this.privateStr = privateStr;
}
void fatherRun() {
System.out.println("父类的方法");
}
}
//子类
public class Child extends Father { }
//测试类
public class MyTest {
@Test
public void run() {
Child child = new Child();
System.out.println(child.publicStr); //直接访问父类的公有属性
System.out.println(child.getPrivateStr()); //父类的私有属性只能通过父类提供的getter
// 和setter访问
child.fatherRun(); //访问父类方法
}
}
运行结果:
父类的公有属性
父类的私有属性
父类的方法
2.1 方法重写:
子类可以重写父类方法,调用时优先使用子类重写方法。
//父类
public class Father {
void run1() {
System.out.println("父类的方法run1");
}
void run2() {
System.out.println("父类的方法run2");
}
}
//子类
public class Child extends Father {
@Override
void run1() {
System.out.println("子类的重写方法");
}
}
//测试类
public class MyTest {
@Test
public void test() {
new Child().run1(); //优先访问子类的重写方法
new Child().run2();
}
}
运行结果:
子类的重写方法
父类的方法run2
这里可以看出,子类重写分类方法后,会优先访问子类的重写方法。
三、多态:相同的引用调用相同的方法出现不同的结果。
多态发生的条件:1、继承 2、重写方法 3、上转型upCasting
//父类
public class People {
void run() {
System.out.println("我是一个人");
}
}
//子类
public class Student extends People {
@Override
void run() {
System.out.println("我是一个学生");
}
}
//子类
public class Teacher extends People{
@Override
void run() {
System.out.println("我是一个老师");
}
}
//测试类
public class MyTest {
@Test
public void test() {
People people = null;
people = new Teacher(); //上转型
people.run();
people = new Student(); //上转型
people.run();
}
}
运行结果:
我是一个老师
我是一个学生