Java 基础
1、面向对象三大特征
1.1 封装
1、封装的概念
(1)封装性是面向对象编程的核心思想
(2)指的就是将描述某种实体的数据和基于这些数的操作集合到一起,形成一个封装体
(3)封装的思想保证了类内部数据结构的完整性,使用户无法轻易直接操作类的内部数据,这样降低了对内部数据的影响,提高了程序的安全性和可维护性。
2、封装的优点
(1)良好的封装能够减少耦合
(2)类内部的结构可以自由修改。
(3)可以对成员变量进行更精确的控制。
(4) 隐藏信息,实现细节。
3、this 关键字
(1)this调用本类中的属性,也就是类中的成员变量;
(2)this调用本类中的其他方法;
(3)this调用本类中的其他构造方法,调用时要放在构造方法的首行。
实例
public class Demo {
public int num;
public Demo(){
this(1); // this关键字调用类中的其他构造函数
}
public Demo(int a){
this.test(); // this关键字调用类中的其他方法
System.out.println(a);
}
public void test(){
this.num = 101; //使用this关键字给成员属性赋值
System.out.println(this.num);
}
public static void main(String[] args) {
Demo demo = new Demo(); 输出: 101 1
}
}
1.2 继承
1、继承的概念
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为
语法:
关键字 extends 表明正在构造的新类派生于一个已存在的类。
已存在的类被称为超类(super class)、基类(base class)或父类(parent class);
新类被称为子类(subclass)、派生类(derived class)或孩子类(child class)。
2、继承的特性
(1)java不支持多继承,即一个子类只能拥有一个父类。
(2)子类对象实例化时一定先实例化父类对象。
(3)java中,所有继承都是公有继承,子类拥有父类非private属性和方法。
(4)在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
3、继承的优缺点
优点:
(1)代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
(2)提高代码的重用性;
(3)子类可以形似父类,但又异于父类;
(4)提高代码的可扩展性,实现父类的方法就可以“为所欲为”了。
缺点:
(1)继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法 ;
(2)降低代码的灵活性。子类必须拥有父类的属性和方法,让子类自由的世界中多了些约束;
(3)增强了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改,而且在缺乏规范的环境下,这种修改可能带来非常糟糕的结果——大段的代码需要重构。
4、类继承初始化过程
public class Animal {
private static int A = printInit("Animal init");
public Animal()
{
System.out.println("--Animal--");
}
public static int printInit(String s)
{
System.out.println(s);
return 1;
}
}
public class Bird extends Animal{
private static int B = Animal.printInit("Bird init");
public Bird()
{
System.out.println("--Bird--");
}
}
public class Maque extends Bird{
private static int m = Animal.printInit("Maque init");
public Maque()
{
System.out.println("--Maque--");
}
public static void main(String[] arg)
{
Maque maque = new Maque();
}
}
运行结果:
Animal init
Bird init
Maque init
--Animal--
--Bird--
--Maque--
从运行结果可以看出
(1)父类的 static 会首先执行,然后是下一个子类,以此类推。这种方式很重要,因为子类的 static 初始化可能会依赖于父类成员能否被正确初始化。 (从虚拟机角度看:虚拟机会保证子类的()方法执行之前,父类的()方法已经执行完毕,()方法是执行的static 变量和static静态语块);
(2)父类的构造器总是在子类的构造过程中被调用,而且按照继承层次逐渐向上链接,以使每个父类的构造器都能得到调用。这样做是有意义的,因为构造器具有一项特殊的任务:检查对象是否被正确的构造或者说是实例化对象。在构造器内部,我们必须确保所要使用的成员都已经构建完毕。为确保这一目的,唯一的办法就是首先调用父类构造器。
5、super 关键字
(1)super只能出现在子类的方法和构造方法中;
(2)super调用构造方法时,只能是第一句(即如果子类的构造方法中需要调用父类的构造方法,必须放在第一行,否则报错);
(3)super不能访问法父类的private成员;
public class Son extends Father {
/**
* 访问父类构造方法
super(); 父类无参的构造方法
super(name); 父类有参的构造方法
*/
public Son(){
super("**"); //必须注意:访问父类的构造函数只能在子类的构造函数中访问,且必须是子类构造函数的第一行
}
public static void main(String[] args) {
Son son = new Son();
}
}
1.3 多态
1、多态的概述
(1)多态是同一个行为具有多个不同表现形式或形态的能力(例如子类和父类具有相同的行为,但子类可以重写父类的方法,形成不同的行为)。
(2)所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
实例
class Animal{
public int month = 2;
public void eat(){
System.out.println("动物吃东西");
}
}
class Dog extends Animal{
public int month = 3;
public void eat() {
System.out.println("小狗吃肉");
}
public void sleep() {
System.out.println("小狗睡午觉");
}
}
class Cat extends Animal{
public int month = 4;
public void eat() {
System.out.println("小猫吃鱼");
}
}
public class Test {
public static void main(String[] args){
Animal a = new Dog();
Animal b = new Cat();
a.eat();
System.out.println(a.month);
//下面代码编译时会出错
// a.sleep();
b.eat();
System.out.println(b.month);
}
}
a对象编译时类型是Animal,运行时类型是Dog;
b对象编译时类型是Animal,运行时类型是Cat。
当运行时调用引用变量的方法时,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征,这就表现出:相同类型的变量调用同一个方法时表现出不同的行为特征,这就是多态。
该例中:当他们调用eat方法时,实际调用的是父类Animal中被覆盖的eat方法。
运行结果:
小狗吃肉
2
小猫吃鱼
2
上例中main方法中注释了a.sleep(),由于a的编译时类型为Animal,而Animal类中没有sleep方法,因此无法在编译时调用sleep方法。
2、多态的三个必要条件
(1)继承
(2)重写
(3)父类引用指向子类对象
3、多态的优点
(1)提高了代码的维护性(继承保证);提高了代码的扩展性
(2) 可替换性
(3)可扩充性
(4)接口性
4、多态的转型
(1)向上转型
多态本身就是向上转型过的过程
使用格式:父类类型 变量名=new 子类类型();
适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。
(2)向下转型
一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用类型转为子类引用各类型
使用格式:子类类型 变量名=(子类类型) 父类类型的变量;
适用场景:当要使用子类特有功能时。
5、多态的实现
(1)基于继承实现的多态
基于继承的实现机制主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。
(2)基于接口实现多态
//创建一个food接口
interface food
{
public void getname();
public void eat();
}
//创建一个fruit接口,继承于food接口
interface fruit extends food
{
//此接口继承了父接口的方法
}
//创建一个meat接口,继承于food接口
interface meat extends food
{
//此接口继承了父接口的方法
}
//ora描述的是橘子,继承于fruit接口
class ora implements fruit
{
public void eat()
{
System.out.println("此方法是吃橘子的方法");
}
public void getname()
{
System.out.println("吃的水果名称为橘子");
}
}
//hotpot类描述的是羊肉,继承于meat接口
class hotpot implements meat
{
public void eat()
{
System.out.println("此方法是吃羊肉的方法");
}
public void getname()
{
System.out.println("吃的肉名称为羊肉");
}
}
//test类描述的是实现多态接口
public class test
{
public static void main(String[] args)
{
food f1=new ora();
f1.eat();
f1.getname();
food f2=new hotpot();
f2.eat();
f2.getname();
}
}