生活角度面向对象:找合适的人做合适的事
生活角度面向过程:亲历亲为,自力更生
类 | 对象 |
---|---|
电脑类 | 我的机械革命 |
汽车类 | 1949红旗 |
人类 | 乔布斯,比尔盖茨,马化腾 |
类:对于一类事物的统称,对当前事务的一些描述,属性描述和行为描述
对象:独立,唯一,特殊的个体
class ClassName{
// 属性描述
// 行为描述
}
要求:
class Person {
// 使用String类型描述Person类的姓名属性
String name;
// 使用int类型描述Person类的年龄属性
int age;
// 使用char类型数据描述Person类的性别属性
char gender;
}
class Person {
// 使用方法描述Person类的吃饭行为
public void eat(String food) {
System.out.println("吃" + food);
}
// 使用方法描述Person类的睡觉行为
public void sleep() {
System.out.println("睡觉了");
}
// 使用方法描述Person类的打豆豆行为
public void daDOUDOU() {
System.out.println("吃饭睡觉打豆豆");
}
}
eclipse快捷键
force模式:ctrl + shift + a 再按一遍切回
类名 对象名 = new 构造方法(所需参数);
// 例:获取一个扫描器对象
// 需要先导包
import java.util.Scanner;
Scanner sc = new Scanner(System.in);
/*
数据类型:
Scanner类型,创建的变量是Scanner的类对象,同时也是一个引用数据类型
sc:
类对象,变量
Scanner的类对象,sc是对象名
new:
申请内存的 堆区 空间,并且清理整个空间中的所有数据
代码中,只要在有new关键字时,一定会用到内存的堆区空间,并且时新的内存空间
Scanner(System.in):
这是一个方法,因为有小括号,没有小括号就是变量
方法名字和类名一致
该方法被称为构造方法,Constructor构造方法
*/
新建两个对象
package cn.ocean888;
class Person {
// 使用String类型描述Person类的姓名属性
String name;
// 使用int类型描述Person类的年龄属性
int age;
// 使用char类型数据描述Person类的性别属性
char gender;
}
public class Demo1 {
public static void main(String[] args) {
Person ocean = new Person();
System.out.println(ocean);
Person ocean2 = new Person();
System.out.println(ocean2);
}
}
输出结果
通过Person类对象,调用类内的成员变量
public class Demo1 {
public static void main(String[] args) {
Person ocean = new Person();
// 赋值
ocean.name = "ocean";
ocean.age = 18;
ocean.gender = '男';
// 取值
System.out.println("name : " + ocean.name);
System.out.println("age : " + ocean.age);
System.out.println("gender :" + ocean.gender);
}
}
类对象.方法名(参数);
package cn.ocean888;
/**
*
* @author q2723
*
*/
class Person {
// 使用方法描述Person类的吃饭行为
public void eat(String food) {
System.out.println("吃" + food);
}
// 使用方法描述Person类的睡觉行为
public void sleep() {
System.out.println("睡觉了");
}
// 使用方法描述Person类的打豆豆行为
public void daDOUDOU() {
System.out.println("吃饭睡觉打豆豆");
}
}
public class Demo1 {
public static void main(String[] args) {
Person ocean = new Person();
// 调用类内的eat方法,注意eat有参则需要传入参数
ocean.eat("bread");
ocean.sleep();
ocean.daDOUDOU();
}
}
类对象内存分析
对象也是引用传参
注意:char的默认值为 ‘\0’ null
类对象地址转移
类对象和数组类似,都是引用传参,栈区存储的是首地址
dog1=dog2,就是把dog2首地址给dog1,此时dog1和dog2都指向原dog2的内存空间,原dog1的空间变为无主空间被释放
找到字节码文件看反编译结果
1.eclipse会自动把.class字节码文件放到指定文件夹
项目名上右击,选择properties
字节码文件在bin目录下
2.在此文件夹打开终端
3.反编译字节码文件命令
Javap -c -l -private .\Person.class
通过反编译工具,发现一些不存在于原来代码中的内容,这些内容是Java编译器为了方便程序开发,提供的必要的无参数构造方法
Java编译器如果发现当前class没有显式自定义构造方法,回默认提供一个无参数构造方法给予使用
如果java编译器发现代码中存在构造方法,java编译器则不会提供无参构造方法
构造方法功能:
初始化当前类对象中保存的成员变量数据
new和构造方法作用:
new
1.根据构造方法提供的数据类型申请对应的堆区内存空间
2.查出整个空间中所有的数据
构造方法
初始化在当前内存堆区空间的成员变量对应的数据
构造方法的书写格式:
public 类名(初始化形式参数列表) {
初始化赋值语句;
}
例1:
并没有构造方法,所以Java编译器将提供默认构造方法Cat
package cn.ocean888;
import java.util.Locale.Category;
class Cat {
String name;
// 并没有构造方法,所以Java编译器将提供默认构造方法Cat
}
public class Demo2 {
public static void main(String[] args) {
// 新建一个cat类
Cat cat = new Cat();
cat.name = "huahua";
System.out.println(cat.name);
}
}
例2:
有无参构造方法,Java编译器不再提供默认构造方法
package cn.ocean888;
import java.util.Locale.Category;
class Cat {
String name;
public Cat() {
System.out.println("this is constructor");
}
}
public class Demo2 {
public static void main(String[] args) {
// 新建一个cat类
Cat cat = new Cat();
cat.name = "huahua";
System.out.println(cat.name);
}
}
例3:
存在有参构造方法,不存在无参构造方法的情况
因为此时java编译器发现代码中存在构造方法,java编译器则不会提供无参构造方法,所以箭头指向位置会报错,需要开发者自己写无参构造方法
package cn.ocean888;
import java.util.Locale.Category;
class Cat {
String name;
// 无参方法
public Cat() {
System.out.println("this is a constructor whitout parameter");
}
// 有参方法
public Cat(int age) {
System.out.println("age:" + age);
}
}
public class Demo2 {
public static void main(String[] args) {
// 新建一个cat对象
Cat cat = new Cat();
// 新建一个有参对象
Cat cat2 = new Cat(2);
cat.name = "huahua";
System.out.println(cat.name);
}
}
例4:
带有两个参数的构造方法
package cn.ocean888;
import java.util.Locale.Category;
class Cat {
String name;
int age;
// 无参方法
public Cat() {
System.out.println("this is a constructor whitout parameter");
}
// 有参方法
public Cat(int age) {
System.out.println("age:" + age);
}
// 两个参数的有参方法
public Cat(int age, String name) {
name = name;
age = age;
System.out.println("有一只" + age + "岁的" + name);
}
}
public class Demo2 {
public static void main(String[] args) {
// 新建一个cat对象
Cat cat = new Cat();
// 新建一个有参对象
Cat cat2 = new Cat(2);
cat.name = "huahua";
System.out.println(cat.name);
// 新建一个两个参数的有参对象
Cat cat3 = new Cat( 5, "加菲猫");
}
}
总结:
这四个方法特点总结:
tips:C语言不允许方法名重复
这就是方法重载
规范:
重载情况下,在同一个类内,不可以出现相同方法名和相同参数数据的方法存在的,只能有一个
原理:
方法名一致的情况下,通过形式参数列表数据类型的不同来选择不同的方法执行
在构造方法中age,name因为就近原则,会被看做是一个局部变量
此时就应该使用this关键字
this
package cn.ocean888;
class Dog {
public Dog() {
System.out.println("address : " + this);
}
}
public class Demo3 {
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println("address : " + dog);
}
}
在输出中可以看出来 this 的就是对象首地址,this 指的就是对象本身
这样的话之前就近原则的问题就可以解决了
this.name就是成员变量,而name是局部变量
new 关键字申请内存空间时,会擦出数据,填入零值
基本数据类型对应的零值
byte short int 0
long 0L
float 0.0F
double 0.0
char '\0' => ascii nul
boolean false
引用数据类型对应的零值
全部为 null
例:
Person null
String str null
int[] arr null
GC(Garbage Collection)
java中内存管理机制就类似于图书管理员身份
优点:
缺点:
特征:
public class Demo4 {
public static void main(String[] args) {
int[] sortedArray = {
1,3,5,6,7,8,9,10,11,23};
int find = 3;
int result = 0;
result = halfSearch(sortedArray, find);
System.out.println(result);
}
/**
* 二分查找
* @param sortedArray 要找的数组,数组必须有序
* @param find 在数组中查找的数据
* @return 以数字形式返回查找结果,-1表示没有找到,数字表示查找数据所在的位置
*/
public static int halfSearch(int[] sortedArray, int find) {
int minIndex = 0;
int maxIndex = sortedArray.length;
int midIndex = (minIndex + maxIndex) / 2;
while (minIndex <= maxIndex ) {
if (sortedArray[midIndex] > find ) {
maxIndex = midIndex - 1;
} else if (sortedArray[midIndex] < find) {
minIndex = midIndex + 1;
} else {
return midIndex;
}
midIndex = (minIndex + maxIndex) / 2;
}
return -1;
}
}
em.out.println(result);
}
/**
* 二分查找
* @param sortedArray 要找的数组,数组必须有序
* @param find 在数组中查找的数据
* @return 以数字形式返回查找结果,-1表示没有找到,数字表示查找数据所在的位置
*/
public static int halfSearch(int[] sortedArray, int find) {
int minIndex = 0;
int maxIndex = sortedArray.length;
int midIndex = (minIndex + maxIndex) / 2;
while (minIndex <= maxIndex ) {
if (sortedArray[midIndex] > find ) {
maxIndex = midIndex - 1;
} else if (sortedArray[midIndex] < find) {
maxIndex = midIndex + 1;
} else {
return midIndex;
}
midIndex = (minIndex + maxIndex) / 2;
}
return -1;
}
}
面向对象三大特征
封装,继承,多态
封装是一个概念,不局限于面向对象的封装
要求:
private关键字是一个权限修饰符
private修饰的成员变量,成员方法,构造方法都是私有化内容,有且只能在类内使用,类外没有任何的操作权限
私有方法不能访问
借助eclipse的outline窗口也可以看到属性和方法的类型
private修饰的成员变量类外是没有任何操作权限,这里需要提供对应的操作方法,setter和getter方法
Setter方法格式:
public void set成员变量名(对应成员变量的数据类型 成员变量的形式参数) {
this.成员变量 = 成员变量的形式参数;
}
例如:
public void setName(String name) {
this.name = name;
}
Getter方法格式:
public 对应成员变量的数据类型 get成员变量名() {
return 成员变量;
}
例如:
public String getName() {
return name;
}
tips:
boolean 类型格式规范
例:
// 定义格式
boolean married;
// getter格式
public boolean isMarried() {
return married;
}
其余数据类型都是getName,setName
自动生成Constructor,Setter,Getter
ctrl + alt + s
ctrl + alt + s
select all
tips:使用时简写eclipse会自动补齐
生成效果
package com.ocean888;
class Cat {
String name;
int age;
char gender;
boolean married;
// 根据实际需要完成对应Constructor,Setter,Getter
public Cat() {
super();
}
public Cat(String name, int age, char gender, boolean married) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.married = married;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public boolean isMarried() {
return married;
}
public void setMarried(boolean married) {
this.married = married;
}
}
public class Demo7 {
public static void main(String[] args) {
Cat cat = new Cat();
cat.setName("xiaohua");
cat.setAge(2);
cat.setGender('雄');
cat.setMarried(false);
System.out.println("name:" + cat.getName());
System.out.println("age:" + cat.getAge());
System.out.println("gender:" + cat.getGender());
System.out.println("married:" + cat.isMarried());
}
}
开发中更多的情况需要多类合作完成,以电脑组装为例,
Demo.java
package com.ocean888;
public class Demo1 {
/*
* 主函数
*/
public static void main(String[] args) throws InterruptedException {
// 新建一个computer对象
Computer computer = new Computer(true);
for (int i = 0; i < 10; i++) {
computer.coumputerRunning();
Thread.sleep(500);
}
computer.setScrennShow(false);
computer.coumputerRunning();
Factory factory = new Factory();
factory.setName("ocean's 小店");
factory.setAddr("北京二仙桥");
factory.setTele(11111111);
factory.repair(computer);
for (int i = 0; i < 10; i++) {
computer.coumputerRunning();
Thread.sleep(500);
}
}
}
Computer.java
package com.ocean888;
public class Computer {
// 成员变量屏幕是否显示
private boolean isScrennShow;
public Computer() {
super();
}
public Computer(boolean isScrennShow) {
super();
this.isScrennShow = isScrennShow;
}
public boolean isScrennShow() {
return isScrennShow;
}
public void setScrennShow(boolean isScrennShow) {
this.isScrennShow = isScrennShow;
}
/*
* 屏幕显示情况判断
*/
public void coumputerRunning() {
if (isScrennShow) {
System.out.println("屏幕显示正常,尽情玩耍吧");
} else {
System.out.println("屏幕显示异常,需要维修!");
}
}
}
Factory.java
package com.ocean888;
public class Factory {
private String name;
private String addr;
private int tele;
public Factory() {
super();
}
public Factory(String name, String addr, int tele) {
super();
this.name = name;
this.addr = addr;
this.tele = tele;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public int getTele() {
return tele;
}
public void setTele(int tele) {
this.tele = tele;
}
public void repair(Computer computer) throws InterruptedException {
if(!computer.isScrennShow()) {
System.out.println("您的电脑已送达" + this.name + ",地址:" + this.addr +",联系电话:" + this.tele);
System.out.println("电脑修理中~~~");
Thread.sleep(1000);
computer.setScrennShow(true);
System.out.println("修理完成");
} else {
System.out.println("检测完毕,电脑没有异常");
}
}
}
tips:Thread.sleep快速修复
使用:
new 构造方法(参数);
用途:
注意:
使用匿名对象不要操作成员变量,有去无回
优点:
package org.ocean888_a;
class Person {
String name;
int age;
}
public class Demo1 {
public static void main(String[] args) {
// new一个对象
Person person = new Person();
person.name = "ocean";
System.out.println(person.name);
// 输出地址
System.out.println(person);
// new一个匿名对象
new Person().name = "ocean";
System.out.println(new Person().name);
// 输出地址
System.out.println(new Person());
}
}
可以看出来匿名对象的地址和普通对象地址不一样,匿名函数尽在创建时有效,所以name=null
Java中的继承是单继承,一个子类只能拥有一个父类,所以 extends 只能继承一个类,所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类
继承使用的关键字
extends
格式:
class A extends B {
}
A是B类的一个子类
B是A类的唯一父类
基本要求:
package org.ocean888_a;
class Father {
// 公共属性
public String name;
// 私有属性
private double salary;
// 无参构造
public Father() {
super();
}
// 有参构造
public Father(String name, double salary) {
super();
this.name = name;
this.salary = salary;
}
// 公共方法
public void game() {
System.out.println("捕鱼达人");
}
// 私有方法
private void testPrivate() {
System.out.println("父类私有方法");
}
}
class Son extends Father {
String name;
int age;
// 无参构造
public Son() {
super();
}
// 有参构造
public Son(String name, double salary, String name2, int age) {
super(name, salary);
name = name2;
this.age = age;
}
public void work() {
System.out.println("就是玩");
}
}
public class Demo2 {
public static void main(String[] args) {
Father father = new Father();
father.name = "小头爸爸";
father.game();
Son son = new Son();
son.age = 12;
son.work();
son.name = "大头儿子";
son.game();
}
}
执行结果
继承父类和子类内存分析图
子类使用父类成员变量和成员方法
package org.ocean888_a;
class Animal {
public String name = "动物";
public void eat() {
System.out.println("父类的eat方法");
}
}
class Dog extends Animal {
public String name = "狗";
public void eat() {
System.out.println("子类的eat方法");
}
public void test() {
// 就近原则
System.out.println(name);
// 使用父类的name属性
System.out.println(super.name);
// 就近原则
eat();
// 使用父类的eat方法
super.eat();
}
}
public class Demo3 {
public static void main(String[] args) {
Dog dog = new Dog();
dog.test();
}
}
super()调用父类的构造方法
super(实际参数)
Java编译器会根据实际参数的数据类型,参数顺序,选择对应的父类构造方法执行,初始化父类的成员空间,方法重载机制
package org.ocean888_a;
class Animal {
String name;
int age;
public Animal() {
System.out.println("父类构造方法");
}
public Animal(String name) {
this.name = "huahua";
System.out.println("单参数构造方法");
}
public Animal(String name, int age) {
this.name = "huahua";
this.age = 1;
System.out.println("双参数构造方法");
}
}
class Cat extends Animal {
public Cat() {
/*
* Constructor call must be the first statement in a constructor
* 必须在第一行,即只能有一个super()
*/
super();
}
}
public class Demo4 {
public static void main(String[] args) {
Cat cat = new Cat();
}
}
程序输出
特点:
子类可以通过继承的方法获取父类中非私有化方法,但是父类的方法,不一定满足子类的情况
方法的重写就是解决在开发过程中,父类的方法不适用于子类的情况,子类可以重写父类的方法,完成自定义方法的使用
重写之后,在没有增加新的方法名的情况下,重写方法体内容,让方法满足子类,降低了开发压力
子类方法重写
按回车
package org.ocean888_a;
class Father {
// 公共属性
public String name;
// 无参构造
public Father() {
}
// 公共方法
public void game() {
System.out.println("捕鱼达人");
}
public void work() {
System.out.println("工人");
}
}
class Son extends Father {
/*
* @Override 注解
* 开启重写严格格式检查
*/
@Override
public void game() {
System.out.println("LOL");
}
@Override
public void work() {
System.out.println("学生");
}
}
public class Demo2 {
public static void main(String[] args) {
Son son = new Son();
son.work();
son.game();
}
}
执行结果
abstract修饰的方法:要求子类强制重写
先贴一个例子
package org.ocean888_b;
abstract class LOLHero {
abstract public void Q();
abstract public void W();
abstract public void E();
abstract public void R();
}
/*
* 子类继承父类可以直接使用父类的方法,但是这种情况下
* 父类的方法不能在子类中使用
*/
class VN extends LOLHero {
@Override
public void Q() {
System.out.println("斩刚闪");
}
@Override
public void W() {
System.out.println("致命打击");
}
@Override
public void E() {
System.out.println("审判");
}
@Override
public void R() {
System.out.println("德玛西亚");
}
}
public class Demo1 {
public static void main(String[] args) {
VN vn = new VN();
vn.Q();
vn.W();
vn.E();
vn.R();
}
}
abstract修饰的方法没有方法体
abstract修饰的方法必须定义在abstract修饰的类内或者interface接口内
一个普通类【非abstract】修饰的类,继承了一个abstract类,强制要求必须实现在abstract类内的所有abstract方法,做到多类规范
如果一个abstract A类继承另一个abstract B类,A类可以选择B类中abstract方法
abstract修饰的类内允许普通方法
abstract修饰的类不能创建自己的类对象,不能实例化,只能被继承
原因:abstract修饰的类内可能存在abstract修饰的方法,而abstract修饰的方法是没有方法体的,如果说创建了abstract修饰类对应的对象,不能执行没有方法体的abstract方法
如果一个abstract类中没有abstract方法,那这个类是没有意义的
package org.ocean888_b;
final class A {
// final修饰成员变量name如果没有初始化会报错
// The blank final field nameString may not have been initialized
// 原因:final修饰的成员变量在定义时必须初始化
public final String nameString = "ocean";
// final关键字修饰的方法不能被子类重写
public final void testA() {
System.out.println();
}
}
// final修饰类
// final class A {
// The type B cannot subclass the final class A
class B extends A {
// 重写A类中的testA方法报错
// Cannot override the final method from A
// 原因:不能重写final关键字修饰的方法
@Override
public void testA() {
System.out.println("重写");
}
}
public class Demo2 {
public static void main(String[] args) {
// final修饰的局部变量
final int num = 10;
num = 20;
// num = 20;报错The final local variable num cannot be assigned. It must be blank and not using a compound assignment
// 原因:final修饰的局部变量一旦被赋值,无法进行修改
}
}
final修饰的成员变量
final修饰的成员变量在定义时必须初始化.并且赋值之后无法修改,一般用于类内带有名字的常量使用
final修饰的成员方法
子类不能重写final关键字修饰的方法,为最终方法,可以用于一些安全性方法的定义
final修饰的局部变量
final修饰的局部变量一旦被赋值,无法进行修改
final修饰的类
final修饰的类为最终类,没有子类,不能被继承
abstract修饰的类不能被final修饰
static关键字的作用是:方便在没有创建对象的情况下调用方法/变量
static修饰成员变量
package org.ocean888_b;
class SingleDog {
// static 修饰的静态成员变量
public static String info = "单身狗";
// 非静态成员便量
public String name;
public SingleDog() {
}
public SingleDog(String name) {
this.name = name;
}
public void test() {
System.out.println("test方法");
}
}
public class Demo3 {
public static void main(String[] args) {
// 在没有对象的情况下,可以直接通过类名调用静态变量
System.out.println(SingleDog.info);
// 匿名对象,运行完毕,对象销毁
new SingleDog();
// 对象销毁之后,静态成员变量依然可以被调用
System.out.println(SingleDog.info);
}
}
静态成员变量和对象无关
从内存角度分析
静态成员变量保存在内存的数据去
类对象占用的实际内存空间是在内存的堆区
两个区域不同
从生命周期分析
静态变量是随着类文件(.class)字节码文件的加载过程中,直接定义在内存的数据区,静态成员变量从程序运行开始就已经存在
类对象是在代码的运行过程中,有可能被创建的,成勋执行过程中,可能会被GC机制回收,程序在退出之前一定会销毁当前Java程序时用到的所有内存
静态成员变量在程序退出之后,才会销毁
静态成员变量的生命周期就是从程序开始到程序结束
类对象只是在创建开始,而且有可能被GC回收
static修饰成员方法
静态成员方法的格式
public static 返回值类型 方法名 (形式参数列表) {
}
注:类方法中可以使用当前类内的静态成员变量,但不允许使用非静态成员变量
static修饰静态成员方法用途
例:自定义数组工具类
package org.ocean888_c;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* 自定义数组工具类
* 工具类中大多数方法,都是静态方法
* @author q2723
*
*/
class MyArrays {
/**
* 数组工具类,数组逆序
* @param arr
*/
public static void reverse(int[] arr) {
for (int i = 0; i < arr.length / 2; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - 1 - i];
arr[arr.length - 1 - i] = temp;
}
}
}
public class Demo1 {
public static void main(String[] args) {
int[] arr = {
1,2,3,4,5,6,7,8};
// 因为是static方法,所以不需要新建对象
MyArrays.reverse(arr);
System.out.println(Arrays.toString(arr));
}
}
构造代码块
成员变量之后,构造方法之前
package org.ocean888_b;
class Dog {
private String name;
// 构造代码块,成员变量之后,构造方法之前
{
System.out.println("构造代码块");
}
// 无参构造
public Dog() {
System.out.println("无参构造");
}
// 有参构造
public Dog(String name) {
System.out.println("有参构造");
}
}
public class Demo4 {
public static void main(String[] args) {
new Dog();
new Dog("ocean");
}
}
局部代码块
提高效率,解决内存,提升jvm回收内存的效率
for() {
}
静态代码块
只要加载类文件,当前静态代码块中内容一定会执行,并且有且只执行一次
static {
// 静态代码块
}
package org.ocean888_b;
class Cat {
static {
System.out.println("静态代码块");
}
}
public class Demo5 {
public static void main(String[] args) throws ClassNotFoundException {
// 强制加载指定类,只会执行一次
Class.forName("org.ocean888_b.Cat");
Class.forName("org.ocean888_b.Cat");
System.out.println("测试静态代码块");
}
}
执行结果:
静态代码块一边用于整个类的初始化
例题:
执行效果:
例二:
结果:程序进入死循环
原因:程序在第一行,new Demo3,Demo3类为本身,所以会出现递归情况,导致程序死循环
编译不报错,运行报错
static修饰静态代码块
interface 接口名 {
成员变量
成员方法
}
类 implements 接口 {
}
implements 可以理解为 遵从
例:
package org.ocean888_d;
interface A{
// 缺省属性 public static final
int num = 10;
// 缺省属性public abstract
void test();
}
/**
* TypeA类遵从接口A
* @author q2723
*
*/
class TypeA implements A {
@Override
public void test() {
System.out.println(num);
System.out.println("接口");
}
}
public class Demo1 {
public static void main(String[] args) {
TypeA typeA = new TypeA();
typeA.test();
}
}
接口间可以继承,而且可以多继承
package org.ocean888_d;
interface B {
// 缺省属性 public static final
int numB = 10;
// 缺省属性public abstract
void testB();
}
interface C {
// 缺省属性 public static final
int numC = 20;
// 缺省属性public abstract
void testC();
}
interface D extends B,C {
// 缺省属性 public static final
int numD = 20;
// 缺省属性public abstract
void testD();
}
class TypeB implements D {
@Override
public void testB () {
}
@Override
public void testC () {
}
@Override
public void testD () {
}
}
public class Demo2 {
}
接口当中的默认方法
default方法,为接口提供了最基本的处理方法,非强制实现,可选
package org.ocean888_d;
interface F {
// 接口当中的默认方法
default void testF() {
System.out.println("接口中默认方法");
}
}
// 没有错误,因为接口中的方法是default方法 修饰,非强制实现
class TypeC implements F {
}
public class Demo3 {
}
接口中成员变量缺省属性 public static final
成员方法缺省属性 public abstract
一个非abstract类遵从interface接口,需要强制完成接口中所有缺省属性为public abstract的成员方法
接口与接口之间,允许使用extends关键字继承,允许一个,继承多个接口,就像生活中的向下兼容问题
接口中使用default关键字修饰方法,default方法拥有方法体,可以认为是非强制实现方法,不要求遵从接口的非abstract强制实现,jdk1.8新特性
生活中映射usb接口实例
鼠标类,键盘类
package org.ocean888_e;
import java.security.PublicKey;
interface USB {
/*
* 要求所有的usb设备,必须完成的方法,告知usb接口连接之后完成的功能是什么
*/
void connect();
}
/*
*
*/
class Mouse implements USB {
@Override
public void connect() {
System.out.println("鼠标链接usb接口,控制光标");
}
}
/*
* logi类继承于Mouse
*/
class Logi extends Mouse {
@Override
public void connect() {
System.out.println("鼠标型号logi m275");
}
}
class Keyboard implements USB {
@Override
public void connect() {
System.out.println("键盘链接usb接口,控制键盘");
}
}
class Ikbc extends Keyboard {
@Override
public void connect() {
System.out.println("键盘型号ikbc w200");
}
}
class PC{
/*
* 电脑类连接usb接口连接方法
* @param usb
*/
public void usbConnect(USB usb) {
// usb设备执行connect方法
usb.connect();
}
}
public class Demo1 {
public static void main(String[] args) {
PC pc = new PC();
Mouse mouse = new Mouse();
Logi logi = new Logi();
Keyboard keyboard = new Keyboard();
Ikbc ikbc = new Ikbc();
pc.usbConnect(mouse);
pc.usbConnect(logi);
pc.usbConnect(keyboard);
pc.usbConnect(ikbc);
}
}
这就是简单的多态
以动物园为例,所有的动物都可以看作一个Animal类,提供喂食方法,和获取动物名字的方法
package org.ocean888_e;
import javax.sound.midi.Soundbank;
class Animal {
}
/**
* Dog类继承Animal类
* @author q2723
*
*/
class Dog extends Animal {
}
/**
* Tiger类继承Animal类
* @author q2723
*
*/
class Tiger extends Animal {
}
/**
* Panda类继承Animal类
* @author q2723
*
*/
class Panda extends Animal {
}
public class Demo2 {
public static void main(String[] args) {
Animal animal = new Animal();
Dog dog = new Dog();
Tiger tiger = new Tiger();
Panda panda = new Panda();
// 投喂动物
feed(animal);
feed(dog);
feed(tiger);
feed(panda);
// 强制类型转换
Dog dog2 = (Dog) getAnimal();
System.out.println(dog2.getClass());
}
/**
* 投喂动物,获取动物对象
* @param animal
*/
public static void feed(Animal animal) {
// 获取当前对象的完整包名.类名
System.out.println(animal.getClass() + "来吃饭" );
}
/**
* 返回动物类对象
* @return
*/
public static Animal getAnimal() {
return new Dog();
}
}
以上的两个案例其实就是多态的使用
作用:
扩宽方法的参数范围
例如上边两个案例中
方法参数为Animal类型
可以传入Animal类型本身,或者传子类对象都可以
public static void feed(Animal animal) {
}
拓宽方法的返回值范围
简化代码开发,提高开发效率,整合数据类型
class Ikbc extends Keyboard {
@Override
public void connect() {
System.out.println("键盘型号ikbc w200");
}
}
class PC{
/*
* 电脑类连接usb接口连接方法
* @param usb
*/
public void usbConnect(USB usb) {
// usb设备执行connect方法
usb.connect();
}
}
public class Demo1 {
public static void main(String[] args) {
PC pc = new PC();
Mouse mouse = new Mouse();
Logi logi = new Logi();
Keyboard keyboard = new Keyboard();
Ikbc ikbc = new Ikbc();
pc.usbConnect(mouse);
pc.usbConnect(logi);
pc.usbConnect(keyboard);
pc.usbConnect(ikbc);
}
}
这就是简单的多态
以上的两个案例其实就是多态的使用
作用:
扩宽方法的参数范围
例如上边两个案例中
方法参数为Animal类型
可以传入Animal类型本身,或者传子类对象都可以
public static void feed(Animal animal) {
}
拓宽方法的返回值范围
简化代码开发,提高开发效率,整合数据类型
多态的更多特征将会以实践案例的方式呈现.