Java面向对象 继承 多态
面向对象 (继承、多态)
1、static静态
static(静态) 关键字
用于修饰成员变量和成员方法
特点:
- 被所有的对象所共享
- 可以使用类名调用
- 静态加载优先于对象
- 随着类的加载而加载
注意事项:
- 静态方法只能访问静态成员
- 非静态方法既可以访问静态也可以访问非静态
- 非静态方法中不可以定义静态变量
- 静态方法中不可以定义this,super关键字
优缺点:
- 优点
- 对对象的共享数据提供单独的存储空间,节省空间
- 直接被类名调用,不用在堆内存创建对象
- 缺点
- 访问出现局限性(只能访问静态)
package one;
/**
* Created by JackFeng on 2020/3/8.
*/
public class StaticDemo {
public static void main(String[] args) {
/*
* Math 主要的数学运算方法
* */
// static double abs ( double a) : 返回绝对值
System.out.println(Math.abs(15));
System.out.println(Math.abs(-10));
System.out.println("----------");
// ceil 天花板 向上取整
System.out.println(Math.ceil(1.2));
System.out.println(Math.ceil(1.6));
System.out.println("----------");
// floor 向下取整
System.out.println(Math.floor(1.2));
System.out.println(Math.floor(1.8));
System.out.println("==========");
// round 四舍五入
System.out.println(Math.round(1.2));
System.out.println(Math.round(1.6));
System.out.println("---------");
// max min
System.out.println(Math.max(3,8));
// pow 次幂 第一个参数的第二个参数次幂
System.out.println("2 的3 次方");
System.out.println(Math.pow(2,3));
// random 随机数 大于0 <1
System.out.println(Math.random());
}
}
2、代码块
写一个数据操作的工具类,取最大值,已经取数组中指定索引的值
MyArray 工具类
package com.a2data;
/**
* Created by JackFeng on 2020/3/13.
*/
public class MyArrays {
// 数组操作 有关的工具类 ,不需要创建对象,所以 可以私有他的构造方法
private MyArrays(){}
// 取最大值
public static int getMax(int[] arr){
// 定义参照物
int max = arr[0];
for (int i = 1; i <arr.length ; i++) {
if (max<arr[i]){
// 替换参照物
max = arr[i];
}
}
return max;
}
// 获取指定数组中指定元素的索引位置
public static int getIndex(int[] arr,int a){
for (int i = 0; i <arr.length ; i++) {
if (arr[i]== a)
return i;
}
return -1;
}
}
MyArrayDemo 工具类使用
package com.a2data;
/**
* Created by JackFeng on 2020/3/13.
*/
public class MyArrayDemo {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 21};
int max = MyArrays.getMax(arr);
System.out.println(max);
int index = MyArrays.getIndex(arr, 3);
int index1 = MyArrays.getIndex(arr, 6);
System.out.println(index);
System.out.println(index1);
}
}
局部代码块:
存在于方法中,控制变量的生命周期(作用域)
构造代码块:
去构造方法中的共性,每次创建对象都会执行,并且在构造方法执行之前执行。
静态代码块:
随着类的加载而加载,只加载一次,加载类时需要加载的驱动
3、继承
继承:Extends
多个类有共同的成员变量和成员方法,抽取到另外一个类中(父类)
只能继承一个父类。 — 只有一个亲爹
只能继承父类非私有成员
支持多层继承 — 还可以有一个亲爷爷
super 与this相似,获取父类的成员和方法。 就近原则!
方法重写:
在子父类当中,子类的方法和父类的方法完全一样,子类重写了父类的方法(覆盖)。并且super 调用父类的方法即可。
注意事项:
- 不能重写父类私有的方法
- 必须大于等于父类方法的权限
注解:@
- @Override
继承中构造方法的执行顺序:
子父类继承关系
- 创建了子类的对象,就会调用子类的构造方法
- 子类构造方法第一行没有调用父类构造方法,默认调用父类无参构造
- 肯定先执行父类方法,因为要先给父类的成员变量进行初始化,子类可能会用到。
super() 在子类构造方法的第一行中调用父类的构造方法
继承优缺点
优点:
- 提高代码的复用性,可维护性
缺点:
- 耦合性的影响。
开发原则: 高内聚低耦合
- 内聚:自己完成某件事的能力
- 耦合:类与类的关系
package com.a2data;
/**
* Created by JackFeng on 2020/3/13.
*/
public class ExtendsDemo {
public static void main(String[] args) {
Zi zi = new Zi();
zi.function();
}
static class Die {
int num = 11;
Die(){
System.out.println("我是父类无参构造");
}
public Die(int num){
System.out.println("我是父类有参构造");
}
public void method(){
System.out.println("我是父类的方法");
}
}
static class Zi extends Die{
int num = 2020;
Zi(){
this(1); // 第一行不调用子类,或者其他方法,默认调用父类
System.out.println("我是子类无参构造");
}
Zi(int num){
System.out.println("我是子类有参构造");
}
public void method(){
System.out.println("我是子类的方法");
}
void function(){
// this.method();
this.num = 20;
}
}
}
this和super的区别
this和super的区别:
- this: 当前对象的引用
- 调用子类的成员变量
- 调用子类的成员方法
- 在子类的构造方法第一行调用子类其他构造方法
- super : 子类对象的父类引用
- 调用父类的成员变量
- 调用父类的成员方法
- 在子类的构造方法第一行调用父类的构造方法
4、匿名对象&final
匿名对象:没有名字的对象
场景:
当方法只是使用一次的时候,可以使用匿名对象
可以当做参数传递,但无法进行操作
注意:
匿名对象可以调用成员对象,并赋值,但是并没有意义,因为只调用一次
package com.a2data;
/**
* Created by JackFeng on 2020/3/13.
*/
public class AnonyDemo {
public static void main(String[] args) {
// Student s = new Student();
// s.study();
new Student(); // 匿名对象,没有变量名引用的对象
}
}
class Student{
String name;
int age;
public void study(){
System.out.println("加油提升自己");
}
}
Final
修饰符: 可以用于修饰类,成员方法和成员变量
final所修饰的类,不可被继承,不能有子类
final所修饰的方法,不能被重写。
final所修饰的变量,是不可修改的,是常量
常量:
- 字面值常量: 1,2,3
- 自定义常量:被final所修饰的成员变量,一旦初始化则不可改变
注意:
- 自定义常量必须初始化,可以选择显示初始化或者构造初始化
5、抽象类
abstract: 关键字,用于修饰方法和类
抽象方法:
不同类的方法是相似的,但是具体内容又不太一样,所以我们智能抽取它的申明,没有具体的方法体,没有具体方法体的方法就是抽象方法
抽象类:
有抽象方法的类必须是抽象类
特点:
- 抽象方法只能在抽象类里边
- 抽象类和抽象方法必须被abstract修饰
- 抽象类不能创建对象(不能实例化)
- 抽象类中可以有非抽象的方法
- 抽象类和类的关系也是继承
抽象类的成员特点
- 成员变量
- 可以有成员变量
- 可以有常量
- 成员方法
- 可以有抽象方法
- 可以有非抽象方法
- 构造方法
- 可以有构造方法的,需要对抽象类的成员变量进行初始化
注意:
一个类继承了抽象类需要重写他所有的抽象方法,否则这个类就得是抽象类
package com.a2data;
import sun.plugin2.message.JavaReplyMessage;
/**
* Created by JackFeng on 2020/3/15.
*/
/*
*
* 普通教练,高级教练
*
*
* 共性:
* 属性 姓名 年龄 性别
* 行为 教学
*
* */
public class AbastractTest {
public static void main(String[] args) {
BasicTeacher bt = new BasicTeacher();
bt.name = "小白教练";
bt.teach();
JobTeacher jt = new JobTeacher();
jt.name = "小灰教练";
jt.teach();
}
}
abstract class Teacher{
String name; // 姓名
int age; // 年龄
String gender;
public abstract void teach();
}
class BasicTeacher extends Teacher{
@Override
public void teach() {
System.out.println(name + "讲基础内容");
}
}
class JobTeacher extends Teacher{
@Override
public void teach() {
System.out.println(name+ "讲高级实战内容");
}
}
6、接口
interface: 接口是一个比抽象类还抽象的类,接口里所有的方法全是抽象方法,接口和类的关系是实现,implements
格式:
interface 接口名 {
}
特点:
- 只能有抽象方法
- 只能有常量
- 只能用 publie&abstract 方法
- 默认使用public static final 来修饰成员变量
- 建议 手动输入默认修饰符(public&abstract),虽然不输入也会是默认的。
注意:
- 接口不能创建对象(不能实例化)
- 类与接口的关系是实现关系,一个类实现一个接口必须实现它的所有方法
类与类:继承关系,单一继承,多层继承
类与接口:实现关系,多实现
接口与接口关系: 继承关系,多层继承
接口优点:
- 1、类与接口的关系,实现关系,而且是多实现,一个类可以实现多个接口,类与类之间是继承关系,java中的继承是单一继承,一个类只能有一个父类,打破了继承的局限性
- 2、对外提供规则(统一要求,例如Use接口,充电器接口)
- 3、降低程序的耦合性
- 定义规则,模块化开发
- 高内聚低耦合,提高开发效率
接口和抽象类的区别:
- 共性: 抽取出抽象的概念
- 区别1:与类的关系
- 类与接口是实现关系,多实现
- 类与抽象类是继承关系,Java中的继承是单一继承,一个类只能有一个父类,java中的继承是多层继承
- 区别2:成员
- 成员变量:
- 抽象类可以有成员变量,也可以有常量
- 接口只能有常量
- 成员方法:
- 抽象类可以有抽象方法,也有非抽象方法
- 接口只能有抽象方法,默认修饰符 public abstract
- 构造方法:
- 抽象类有构造方法的
- 接口没有构造方法
接口开发的思路
分析:
由下至上 不断向上抽取
实现:
由上至下 先实现共性
应用:
使用具体的子类
package com.a2data;
/**
* Created by JackFeng on 2020/3/15.
*/
/*
*
* 篮球运动员和教练
* 乒乓球运动员和教练
* 篮球运动员和教练要出国访问,需要学习英语
*
*
*
* */
public class InterfaceTest {
public static void main(String[] args) {
//篮球运动员对象
BasketBallPlayer bp = new BasketBallPlayer();
bp.name = "姚明";
bp.age = 35;
bp.gender = "男";
bp.sleep();
bp.study();
bp.speak();
System.out.println("------------");
//乒乓球教练对象
PingpangCoache pp = new PingpangCoache();
pp.name = "刘教练";
pp.age = 40;
pp.gender = "男";
pp.sleep();
pp.teach();
// pp.speak()
}
}
class Person{
String name;
int age;
String gender;
public Person() {
}
public Person(String name, int age, String gender) {
// 成员变量初始化
this.name = name;
this.age = age;
this.gender = gender;
}
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
interface SpeakEnglish {
public abstract void speak();
}
// 运动员
abstract class Player extends Person{
//学习
public abstract void study();
}
// 教练
abstract class Coach extends Person{
// 教
public abstract void teach();
}
//篮球运动员
class BasketBallPlayer extends Player implements SpeakEnglish{
@Override
public void study() {
System.out.println("学扣篮");
}
@Override
public void speak() {
System.out.println("说英语");
}
}
//乒乓球运动员
class PingpangPlayer extends Player{
@Override
public void study() {
System.out.println("学颠球");
}
}
//篮球教练
class BasketBallCoach extends Coach implements SpeakEnglish{
@Override
public void teach() {
System.out.println("教扣篮");
}
@Override
public void speak() {
System.out.println("说英语");
}
}
//乒乓球教练
class PingpangCoache extends Coach{
@Override
public void teach() {
System.out.println("教颠球");
}
}
7、多态
前提
多态的前提:
- 子父类继承关系
- 方法的重写
- 父类引用指向子类对象
动态绑定:运行期间调用的方法,是根据具体的类型,具体的方法
优缺点:
- 优点: 可以提高可维护性(多态前提所保证的),提高代码的可扩展性
- 缺点: 无法直接访问子类特有的成员
package com.a2data;
/**
* Created by JackFeng on 2020/3/15.
*/
public class PoymorphicDemo {
public static void main(String[] args) {
// Cat cat = new Cat();
// cat.eat();
// 父类引用 Animal a
// 指向 =
// 子类对象 new Cat()
// 动态绑定
Animal a = new Cat();
a.eat();
}
}
class Animal {
public void eat(){
System.out.println("c吃东西");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
}
特点
多态的成员特点:
- 成员变量
- 编译时看的是左边,运行时看的是左边
- 成员方法
- 编译时看的是左边,运行时看的是右边
- 静态方法
- 编译时看的是左边,运行时看的是左边
编译时看的都是左边,运行时成员方法看的是右边,其他(成员变量和静态方法)看的都是左边
package com.java;
import java.util.Date;
/**
* Created by JackFeng on 2020/3/15.
*/
public class PoymorphicDemo {
public static void main(String[] args) {
// 成员变量
// 在继承中没有被重写的概念,没有动态绑定的概念
// 执行的是父类的
Dad d = new Kid();
System.out.println(d.num);
// 成员方法
// 运行看右边
System.out.println("----------");
d.method();
// 静态方法
d.function(); // 使用变量去调用静态方法,相当于用变量类型的类名去调用 所以输出父类的静态方法
}
}
class Dad{
int num = 1;
public void method(){
System.out.println("我是父类的方法");
}
public static void function(){
System.out.println("我是父类的静态方法");
}
}
class Kid extends Dad{
int num = 21;
public void method(){
System.out.println("我是子类的方法");
}
public static void function(){
System.out.println("我是子类的静态方法");
}
}
多态转型
多态中的向上转型和向下转型:
- 引用类型之间的转换
- 向上转型
- 由小到大(子类型转换成父类型)
- 向下转型
- 由大到小
- 基本数据类型的转换
- 自动类型转换
- 由小到大
- byte short char – int — long — float – double
- 强制类型转换
- 由大到小
package com.java;
/**
* Created by JackFeng on 2020/3/15.
*/
public class polymorphicDemo {
public static void main(String[] args) {
Animal a = new Dog(); // 向上转型
a.eat();
Dog d = (Dog) a; // 向下转型 本身是什么类型 转换成什么类型
d.swim();
}
}
class Animal{
public void eat(){
System.out.println("吃东西");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("啃骨头");
}
public void swim(){
System.out.println("狗刨");
}
}
8、权限修饰符
包
特点:(package)
- 可以由多层
- 不同包下的文件名可以重复
- 包的声明必须在第一行代码
包使用场景
类的全名: 包名.类名
同包:
相同包下的类可以直接访问,不需要做其他的操作
异包:
1、使用类的全名
2、使用关键字import将类导入
注意:
***** 代表的是通配符,代表导入了这个包下所有的类,并没有导入子包下的类
权限修饰符
pubilc —- 访问都是对外的
- 当前类,相同包下不同的类,不同包下的类
default
- 当前类,相同包下不同的类
- 当前包下使用(与protected)区别
private
- 仅限当前类
protected — 数据保护
- 当前类,相同包下不同的类
- 让子类对象使用
9、内部类
成员内部类
1、在类的成员位置,和成员变量以及成员方法所在的位置是一样的
2、在内部类当中,可以直接访问外部类的成员,包括私有成员
修饰符:
- 可以使用权限修饰符修饰成员内部类,但是如果使用私有来修饰,则无法在其他类中访问
- 可以使用static 修饰成员内部类,不用再创建外部类对象
匿名内部类:
必须在定义匿名内部类得时候创建它得对象
格式:
new 类/接口(){
继承这个类得子类对象,可以重写父类方法
实现这个类得子类对象,必须实现这个接口得所有方法
};
原理:
- 创建了继承这个类得子类对象或者创建了实现这个接口得子类对象
应用场景:
- 作为参数传递
package com.java;
/**
* Created by JackFeng on 2020/3/15.
*/
public class InnerDemo {
public static void main(String[] args) {
Outer.Inner i = new Outer().new Inner();
i.function();
}
}
class Outer{
private int num = 10;
public void method(){
Inner i = new Inner();
i.function();
}
class Inner{
public void function(){
// 私有成员 可以i直接访问
System.out.println(num);
}
}
}