封装
程序设计的要求是:高内聚,低耦合。高内聚就是程序内部的数据操作细节自己完成,不允许外部干涉;低耦合是仅暴露少量的方法给外部使用。
而封装就是数据的隐藏,禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问,这称为信息隐藏。
封装具有以下作用:
- 提高程序的可维护性
- 统一接口
- 隐藏代码的实现细节
- 提高程序的安全性,保护数据
public class OverLoadingDemo {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age >100 || age < 0) {
System.out.println("该年龄不合法!");
System.exit(0);
} else {
this.age = age;
}
}
}
public class Test {
public static void main(String[] args) {
OverLoadingDemo student = new OverLoadingDemo();
//student.name;
//属性私有的变量在其他类中无法直接调用
student.setName("Ayin");
System.out.println(student.getName());
student.setAge(150);
System.out.println(student.getAge());
}
}
继承
继承的本质是对一堆类的抽象,从而对现实世界更好地建模。
关键字:extends,扩展,意思是子类对父类的扩展,子类一旦继承了父类,就会拥有父类的全部方法(拥有私有属性的变量需要使用封装思想)。且Java中只有单继承,没有多继承。继承是类和类之间的关系,除此之外,类和类之间的关系还有依赖,组合,聚合等。
在Java中,所有的类,都会直接或者间接继承Object类。
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void say() {
System.out.println(this.name + "说了一句话!");
}
}
public class Student extends Person{
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("Ayin");
student.say();
}
}
可以到Student类中并没有定义任何变量,但是在测试类中,对Student类进行实例化,却可以调用Person类中的方法,这是因为Student类继承了Person类,Student作为子类,继承了父类Person类中的所有方法。
super关键字
注意点:
- super调用父类的构造方法,且必须是构造方法中的第一个
- super只能出现在子类的方法或者是构造方法之中
- super和this不能同时调用构造方法
super与this的区别
-
代表的对象不同:
this:代表调用者本身的对象
super:代表父类的引用
-
前提不同:
this:即便没有继承也可以使用
super:仅在继承的条件下使用
-
构造方法不同:
this();代表着本类的构造,而super();代表着父类的构造。
关于构造器:
子类中创建的构造方法会默认先调用父类的无参构造,且子类调用父类构造器,子类的构造器中,super关键字必须写在第一行,如果父类中重写了有参的构造方法,那子类中也必须调用父类中的有参构造。
public class Person {
protected String name = "Ayin01";
public Person() {
System.out.println("调用了父类的无参构造");
}
public void print() {
System.out.println("Person");
}
}
public class Student extends Person{
private String name = "Ayin02";
public Student() {
System.out.println("调用了子类的无参构造");
}
public void testPrint() {
print();
this.print(); //this调动当前类本身的方法
super.print(); //super调用父类的方法
}
public void testPrint(String name) {
System.out.println(name);
System.out.println(this.name); //this调动当前类本身的对象
System.out.println(super.name); //super调用父类的引用
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
//调用了父类的无参构造
//调用了子类的无参构造
student.testPrint("Ayin03");
//Ayin03
//Ayin02
//Ayin01
student.testPrint();
//Student
//Student
//Person
}
}
方法重写
方法重写需要有继承关系,子类重写的是父类的方法,并不是重写父类的属性。当父类的功能,子类不一定需要,或者不一定满足的时候,就可以进行方法重写。
无法进行方法重写的几种情况:
- static方法
- final关键字修饰的方法
- private方法
注意点:
1. 方法名必须相同
2. 参数列表必须相同
3. 修饰符的范围可以扩大但不能缩小:public>protected>default>private
4. 抛出异常的范围可以缩小,但不能扩大
public class A {
public static void print() {
System.out.println("A-->print()");
}
}
public class B extends A{
public static void print() {
System.out.println("B-->print()");
}
}
public class Test {
public static void main(String[] args) {
//方法的调用只和左边定义的数据类型有关
B b = new B();
b.print();//B-->print()
A a = new B(); //父类的引用指向了子类,
a.print();//A-->print()
}
}
静态方法和非静态方法的区别很大,静态方法会调用的是类的方法,而非静态方法调用的是对象的方法。
public class A {
public void print() {
System.out.println("A-->print()");
}
}
public class B extends A{
@Override
public void print() {
System.out.println("B-->print()");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.print();//B-->print()
A a = new B();
a.print();//B// -->print()
}
}
多态
多态是指同一个方法可以根据发送的对象不同而采用多种不同的行为方式,且一个对象的实际类型是确定的,但是指向对象的引用类型可以有很多种。
多态存在的条件:
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
注意:多态是方法的多态,属性并没有多态。
public class Person {
public void run() {
System.out.println("Person is running");
}
}
public class Student extends Person{
@Override
public void run() {
System.out.println("Student is running");
}
public void eat() {
System.out.println("Student is eatting");
}
}
public class Test {
public static void main(String[] args) {
// 正常调用子类所有的方法,包括重写的父类方法
Student s1 = new Student();
s1.run(); // Student is running
// s1.eat();
// 可以指向子类型,但是不能调用子类独有的方法,也就是说,这里是没有s2.eat这种写法的
Person s2 = new Student();
// 执行的是父类的方法,子类重写了父类的方法
s2.run(); //Student is running
}
}
类型转换
通过父类的引用去指向子类的对象,调用原本父类不存在的方法时,需要进行类型转换。
类型的高低:父类(高)—>子类(低)
类型转换分为两种情况,一是由高位往低位转换,二是由低位往高位转换。
高转低不需要强制转换,而低转高需要强制转换。
public class Test {
public static void main(String[] args) {
Person s2 = new Student();
Student s3 = (Student) s2;
s3.eat();
//((Student) s2)).eat();
}
}