面对对象编程
一、包
1、定义 :
包 即组织类的一种方式 通俗的来说 可以理解为文件夹
作用:确保类的唯一性
如何导入包中的类
1、命令行
首先对于一个 .java的文件 使用命令行进行编译运行时,
(1)当jvm的启动方式为当前 .java文件,为平时一般的命令 (javac 文件名.java、java 文件名)
(2)当jvm的启动方式在当前 .java 的文件,而是别的路径,此时编译运行的命令为 (javac 路径\路径\路径 文件名.java 、 java 路径.l路径.路径. 文件名),而对于.java文件里的程序 要声明包 package 路径
2、IDEA导入包
idea中导入包,用import
如要导入日期 import java.until.Date
若要导入 java.until的其他的 可以使用 java.until.* 代表所有的
3、静态导入包
即在导入包的语句中加 static
例如:import stati java.lang.System.*
4、将类放入包中
(1)先在IDEA中新建一个包,即右键src-新建-packa
(2)弹出的对话框中写上包名 (包名应与路径名相匹配,且尽量指定为唯一的名字。如:包名 com.bit.demo1 其路径也为com\bit\demo1)
(3)在包中创建类,即右键包名-新建-class 输入类名即可。
5、包的访问权限
访问权限修饰符有:public、private、protecte、default
若不写则默认为default 包访问
若某个成员包含public private,则这个成员可以在包内部的其他类被访问,但是不可以在包外部,
总之default的访问权限 只限制于在包的内部访问
二、继承
is -a的关系
1、定义
class 子类 extens 父类{
}
继承的作用:代码的复用 减少代码的冗余
注意:
(1)子类继承父类除构造方法外的其他东西
对于父类的private的字段和方法,子类无法访问
(2)子类—》父类(超类)
派生类—》基类
2、protecte
类的子类和同一包中其他类可以,可以访问protected
各个修饰符的访问权限:
3、final关键字
final 可以修饰变量或字段 表示常量
当它修饰一个类时,则表示这个类不能被继承 称为密封类
作用:限制 类被继承
4、super关键字
1、调用父类的方法 super.func()
2、调用父类的属性 super.data();
3、调用父类的构造方法 super(); 必须放在第一行
注意:
子类的构造时,首先需要构造父类
在子类的构造中 super 调用父类的构造方法帮助父类进行构造
如:
`public Cat (String name,int age){
super(name,age) //调用父类的
}`
super和this的区别
4、 继承中静态代码块和实例代码块及构造方法的运行的顺序:
父类的静态
子类的静态
父类的实例代码
父类的构造方法
子类的实例
子类的构造方法
三、组合
组合 a par tof/has a 的关系
四、多态
1、向上转型
子类赋值给父类
(1)父类的引用,引用子类的对象
如:
Animal bird2 = new Bird("aa");
此时bird2是父类(animal)的引用,指向子类(bird)的实例
(2)发生的时机
直接赋值
方法传参
方法返回
2、动态绑定
运行时发生动态绑定
(1)当子类和父类中出现同名方法,在调用时:
若父类的引用指向子类的实例,则调用子类的方法,当父类的引用指向父类的实例,则调用父类的方法
总结:
在 Java 中, 调用某个类的方法, 究竟执行了哪段代码 (是父类方法的代码还是子类方法的代码) , 要看究竟这个引用指向的是父类对象还是子类对象. 这个过程是程序运行时决定的(而不是编译期), 因此称为 动态绑定
(2)查看动态绑定
javap -c 文件名.java
IDEA 反汇编
invokspecial:构造方法
invokevirtual:实例方法 /虚方法
invokestatic:静态方法
方法表:
方法表是一个类型一张,class对象和方法表 和类型是一一对应的。
例如 Animal animal = new Cat(豆豆,19,man)
animal在栈上 存放着在堆上的对象cat (cat 里包含着继承的父类的属性以及自己的属性) 这个对象有一个方法表的地址 (有了对象才有方法表的地址)
方法表 存放在方法区内
方法表:存放方法名称和方法地址
表头为 class对象的地址
class对象存放在方法区
class对象和方法表 和类型一一对应
class对象是唯一的
方法表的产生:是在编译的时候产生的
(3)发生动态绑定的前提
父类引用子类的对象
子类和父类有同名的覆盖方法
若通过父类的引用调用这个重名的方法,就会发生动态绑定
方法重写
1、定义
子类实现父类同名方法,参数类型和个数相同,返回值相同(可以不同,但是返回值之间需要构成协变类型)称为重写/覆盖
协变:返回值之间构成继承关系
2、不能再同一个类中
3、重写不能static方法,private也不能重写
4、重写中子类的方法的访问权限不能低于父类的方法访问权限
扩展:
重载和重写的区别:
五、多态
动态绑定 – 运行时多态
静态多态 --调用静态方法----编译时多态
1、怎样理解动态:
即 一种事物多种形态;
从程序层次,父类引用子类的对象,且子类和父类有同名的覆盖方法,若通过父类的引用调用这个重名的方法,就会发生动态绑定
2、作用
类的调用者对类的使用成本进一步降低
可扩展能力强
class Shape {
public void draw() {
System.out.println("Shape::draw()");
}
}
class Cycle extends Shape{
@Override //ctrl+o重写
public void draw() {
System.out.println("画圆");
}
}
class Rect extends Shape{
@Override
public void draw() {
System.out.println("画矩形");
}
}
class Triangle extends Shape {
@Override//重写
public void draw() {
System.out.println("画三角形");
}
}
public class TestDemo {
public static void drawMap(Shape shape) {
shape.draw();
}
public static void main(String[] args) {
Shape shape = new Cycle();
Shape shape1 = new Rect();
Shape shape2 = new Triangle();
drawMap(shape);
drawMap(shape1);
drawMap(shape2);
}
}
六、向下转型
1、父类赋值给子类
强制类型转化
Cat cat = (Cat)animal; cat.run();
前提:当前的引用是某个类的实例
Cat 是 animal的实例
instanceof 可以判定一个引用是否是某个类的实例
向下转型 一定要发生向上转型 且一定是父类的一个实例
A of B -> B 的 A
七、抽象类
1、定义
abstract class Shape {
abstract public void draw();//若一个方法为抽象方法,则不需要实现
}
注意:
若一个方法为抽象方法,则类必须为抽象类 abstrat
2、抽象类可以包含抽象方法 也可以包含非抽象方法
3、抽象类不可以被实例化,不能new
Shape shape = new Shape();//错误
若要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法
4、抽象类被继承
一个普通的类如果继承抽象类,继承时 子类要重写抽象类的抽象方法 即实现抽象方法
5、抽象类A可以继承抽象类B,此时不需要重写被继承的抽象类的抽象方法
6、若一个普通类C继承了上述抽象类A,(子类:抽象A 继承了 父类:抽象B,派生类 普通C 继承 基类:抽象A)
若抽象类A没有重写抽象方法,那么当前的普通类C一定要重写抽象方法
7、抽象方法一定不能是private修饰, 抽象类不能被final所修饰(抽象类出现,为了被继承)
8、抽象类也可以发生向上转型
八、接口
1、接口中包含的方法都是抽象方法, 字段只能包含静态常量
2、IDEA创建接口 ,src-右键-new class-下拉框kind -选择接口interface
3、定义:
interface IShape { //以I开头表示接口
public abatract final int a = 10;
public abatract void draw();
}
实现
Class Cycle2 implements Ishape(){ //重写 void draw 方法 }
4、接口中的方法一定不能有具体的实现, 都是出现方法 若不加static 默认为 public abatract 方法
5、若定义 int a=10;则默认为 public static final
6、普通的类不能继承接口,但是可以实现implements
若实现,一定要重写方法
7、接口不能实例化 但是可以发生向上转型
IShape shape = new Cycle();
8、接口可以实现多个接口
一个类可先继承另一个类再实现接口:
(1)首先继承的类 要提供构造方法;
(2)然后再重写接口里的方法。
implements A接口,B接口
//A接口
interface IFlying {
void fly();
}
//B接口
interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
class Cat extends Animal implements IRunning {
//构造方法
public Cat(String name) {
super(name);
}
//重写接口方法
@Override
public void run() {
System.out.println(this.name + "正在用四条腿跑");
}
}
//多接口
class Frog extends Animal implements IRunning, ISwimming {
public Frog(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.name + "正在往前跳");
}
@Override
public void swim() {
System.out.println(this.name + "正在蹬腿游泳");
}
}
9、接口和接口之间是不能发生实现的,但它们之间可以继承, 继承可以多继承
interface c extends B{
}
nterface c extends B ,A{
}
10、接口是为了多继承