一、封装
1.封装概述:
Java 语言的基本封装单位是类。由于类的用途是封装复杂性,所以类的内部有隐藏实现复杂性的机制。Java 提供了私有和公有的访问模式,类的公有接口代表外部的用户应该知道或可以知道的每件东西,私有的方法数据只能通过该类的成员代码来访问,
2.封装概念:
封装是将代码及其处理的数据绑定在一起的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。封装的目的在于保护信息,使用它的主要优点如下:
1)、保护类中的信息,它可以阻止在外部定义的代码随意访问内部代码和数据。
2)、隐藏细节信息,一些不需要程序员修改和使用的信息,比如取款机中的键盘,用户只需要知道按哪个键实现什么操作就可以,至于它内部是如何运行的,用户不需要知道。
3)、有助于建立各个系统之间的松耦合关系,提高系统的独立性。当一个系统的实现方式发生变化时,只要它的接口不变,就不会影响其他系统的使用。例如 U 盘,不管里面的存储方式怎么改变,只要 U 盘上的 USB 接口不变,就不会影响用户的正常操作。
4)、提高软件的复用率,降低成本。每个系统都是一个相对独立的整体,可以在不同的环境中得到使用。例如,一个 U 盘可以在多台电脑上使用。
3.修饰符:
1)、public:可用于方法、属性、类本身。可用于所有地方。
2)、private:只能修饰方法和属性。只能在本类中被访问
3)、default(默认):可以用于方法,属性、类本身。能被该类所属的包中的所有类访问。
4)、protected:可用于方法、属性。能被该类所属的包中的所有类访问,可以被不同包中的子类访问(继承)。
4.访问权限:
访问级别 | 访问控制修饰符 | 同类 | 同包 | 子类 | 不同包 |
---|---|---|---|---|---|
公开 | public | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
受保护 | protected | 可以访问 | 可以访问 | 可以访问 | 不可以访问 |
默认 | 没有修饰符 | 可以访问 | 可以访问 | 不可以访问 | 不可以访问 |
私有 | private | 可以访问 | 不可以访问 | 不可以访问 | 不可以访问 |
二、继承
1.概述:
程序中的继承性是指子类拥有父类的全部特征和行为,这是类之间的一种关系。通过继承可以减少代码冗余,提高程序运行效率。
Java 只支持单继承。
2.语法:
extends关键字
public class Person{
}
class Student extends Person{
}
注意:
1)、类的继承不改变类成员的访问权限,也就是说,如果父类的成员是公有的、被保护的或默认的,它的子类仍具有相应的这些特性,并且子类不能获得父类的构造方法。
2)、如果在父类中存在有参的构造方法而并没有重载无参的构造方法,那么在子类中必须含有有参的构造方法,因为如果在子类中不含有构造方法,默认会调用父类中无参的构造方法,而在父类中并没有无参的构造方法,因此会出错。
3.关于super();
概述:
由于子类不能继承父类的构造方法,因此,要调用父类的构造方法,必须在子类的构造方法体的第一行使用 super() 方法。该方法会调用父类相应的构造方法来完成子类对象的初始化工作。
在以下情况下需要使用 super 关键字:
1)、在类的构造方法中,通过 super 语句调用该类的父类的构造方法。
2)、在子类中访问父类中的成员。
使用super();调用父类的构造函数:
super 用来直接调用父类中的构造方法,使用它可以使书写代码更简洁方便。
public class Person{
private int age;
private String name;
private String sex;
public Person(int age,String name){
this.age = age;
this.name = name;
}
}
class Student extends Person{
public Student(int age,String name,String sex){
super(age,name);//调用父类的构造方法
this.sex = sex;
}
}
使用super();访问父类成员:
使用 super 访问父类中的成员与 this 关键字的使用相似,只不过它引用的是子类的父类。另外,super 还可以用于调用被子类隐藏的方法。
4.方法的重载与重写:
1)重载:
概述:
Java 允许同一个类中定义多个同名方法,只要它们的形参列表不同即可。如果同一个类中包含了两个或两个以上方法名相同的方法,但形参列表不同,这种情况被称为方法重载(overload)。
例:
class Test{
void test(int i){
System.out.println("输入参数为int型");
}
void test(String s){
System.out.println("输入参数为String型");
}
void test(double d){
System.out.println("输入参数为double型");
}
public static void main(String[] args) {
test(1);
test("s");
test(2.0);
}
}
//输出结果为:
输入参数为int型
输入参数为String型
输入参数为double型
根据参数的不同来区分,以进行不同的格式化处理和输出。它们之间就构成了方法的重载。实际调用时,根据实参的类型来决定调用哪一个方法。
方法重载的要求是两同一不同:
同一个类中方法名相同,参数列表不同。至于方法的其他部分,如方法返回值类型、修饰符等,与方法重载没有任何关系。
2)重写:
概述:
在子类中如果创建了一个与父类中相同名称、相同返回值类型、相同参数列表的方法,只是方法体中的实现不同,以实现不同于父类的功能,这种方式被称为方法重写(override),又称为方法覆盖。当父类中的方法无法满足子类需求或子类具有特有功能的时候,需要方法重写。
规则:
a)、参数列表必须完全与被重写的方法参数列表相同。
b)、返回的类型必须与被重写的方法的返回类型相同。
c)、访问权限不能比父类中被重写方法的访问权限更低(public>protected>default>private)。
d)、重写方法一定不能抛出新的检査异常或者比被重写方法声明更加宽泛的检査型异常。例如,父类的一个方法声明了一个检査异常 IOException,在重写这个方法时就不能抛出 Exception,只能拋出 IOException 的子类异常,可以抛出非检査异常。
另外还要注意以下几条:
重写的方法可以使用 @Override 注解来标识。
父类的成员方法只能被它的子类重写。
声明为 final 的方法不能被重写。
声明为 static 的方法不能被重写,但是能够再次声明。
构造方法不能被重写。
子类和父类在同一个包中时,子类可以重写父类的所有方法,除了声明为 private 和 final 的方法。
子类和父类不在同一个包中时,子类只能重写父类的声明为 public 和 protected 的非 final 方法。
如果不能继承一个方法,则不能重写这个方法。
3)总结:
位置 | 方法名 | 参数表 | 返回值 | 异常 | 访问修饰符 | |
---|---|---|---|---|---|---|
重写 | 子类 | 相同 | 相同 | 相同 | 有限制 | 有限制 |
重载 | 同类 | 相同 | 不同 | 无关 | 无关 | 无关 |
三、多态
1)、概述:
多态是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,这使得同一个属性或方法在父类及其各个子类中具有不同的含义。
Java 实现多态有 3 个必要条件:继承、重写和向上转型。
2)、例:
public class Shape{
private double Height;
private double Wide;
void area(double Height,double Wide){
//用于计算对象面积
System.out.println("形状未知,无法计算");
}
}
class Squre extends Shape{
void area(double Height,double Wide){
//用于计算对象面积
System.out.println("正方形面积为:"+Height*Wide);
}
}
class Triangle extends Shape{
void area(double Height,double Wide){
//用于计算对象面积
System.out.println("三角形面积为:"+Height*Wide*0.5);
}
}
class Test{
public static void main(String[] args) {
Shape shape;
shape = new Shape();
shape.area(3,5);
System.out.println("---------------");
shape = new Squre();
shape.area(3,5);
System.out.println("---------------");
shape = new Triangle();
shape.area(4,5);
}
}
//运行结果为:
形状未知,无法计算
---------------
正方形面积为:15.0
---------------
三角形面积为:10.0
由上述代码可见:无论 shape变量的对象是 Squre还是 Triangle,它们都是 Shape类的子类,因此可以向上转型为该类,从而实现多态。
3)关于向上转型与向下转型
向上转型: 子类引用的对象调用父类的方法,自动。
向下转型: 父类去使用子类的方法,强制转换
例:
class A{
public void print(){
System.out.println("这是父类的方法");
}
}
class B extends A{
public void print(){
System.out.println("这是子类覆盖父类后的方法");
}
public void Bprint(){
System.out.println("这是子类独有的方法");
}
}
class Test{
A a = new B();//向上转型
a.print();
B b = (B)a;
b.Bprint();//向下转型
}
运行结果:
这是子类覆盖父类后的方法
这是子类独有的方法
注:
1)、倘若不进行向下转型,直接利用A类对象a是无法直接调用子类独有的方法Bprint()的,因为该方法是定义在子类的,想要使用子类独有的方法,要创建子类实例,那么需要进行向下转型操作。
2)、在进行对象的向下转型之前,必须首先发生对象的向上转型操作,否则将出现对象转换异常。
3)、如果发生了向上转型,那么所调用的方法一定是被子类覆盖过的方法。