目录
内容非常多而全面,建议使用目录
一. 权限修饰符
概念: 就是java中的一些关键字, 关键字的作用控制当前内容被访问的权限
分类:
public: 如果一个内容被public修饰, 谁来都能访问
protected:
默认(什么都不写):
private:如果一个内容被private修饰, 除了当前类自己, 谁来都不能访问
二. 继承
2.1 前提
public class Cat {
//行为
public void sleep(){
System.out.println("睡觉觉~");
}
public void drink(){
System.out.println("喝水水~");
}
public void eat(){
System.out.println("吃鱼~");
}
}
public class Dog {
//行为
public void sleep(){
System.out.println("睡觉觉~");
}
public void drink(){
System.out.println("喝水水~");
}
public void eat(){
System.out.println("吃骨头~");
}
}
上述两份代码中有重复的代码, 希望这些重复的代码不要多次书写,此时需要使用继承
2.2 概述
概念: 面向对象语言的三大特性之一, 描述的类与类之间的关系
作用: 当A类与B类有继承关系的时候, 那么A类中就可以使用B类中所有非私有的内容
格式: class A extends B{}
三. 继承的初步使用
//抽取cat类和dog类中共性的内容
public class Animal {
public void sleep(){
System.out.println("睡觉觉~");
}
public void drink(){
System.out.println("喝水水~");
}
}
//让cat类继承Animal类 Animal是父类, Cat是子类
public class Cat extends Animal {
//行为
public void eat(){
System.out.println("吃鱼~");
}
}
public class Dog extends Animal{
//行为
public void eat(){
System.out.println("吃骨头~");
}
}
public class Test {
public static void main(String[] args) {
//测试Cat
Cat c = new Cat();
c.eat();
//ctrl+鼠标移动 变小手
c.drink();
c.sleep();
System.out.println("=====================");
//测试Dog
Dog d = new Dog();
d.eat();
d.drink();
d.sleep();
}
}
四. 方法重写
4.1 前提
当从父类中继承的内容不能满足子类需求时,子类可以重写父类的方法
4.2 概念
当子类中出现了和父类一模一样的方法声明时, 子类就重写了父类的方法
//抽取cat类和dog类中共性的内容
public class Animal {
public void sleep(){
System.out.println("睡觉觉~");
}
public void drink(){
System.out.println("喝水水~");
}
}
//让cat类继承Animal类 Animal是父类, Cat是子类
public class Cat extends Animal {
//重写父类的drink方法
@Override//作用: 检查子类是否正确的重写了父类的方法
public void drink(){
System.out.println("喝水水~");
System.out.println("舔舔嘴~");
}
//生成重写的代码: 写方法名+回车
//行为
public void eat(){
System.out.println("吃鱼~");
}
}
public class Test {
public static void main(String[] args) {
Cat c = new Cat();
c.drink();
}
}
4.3 继承中方法的调用规则
当使用子类对象调用方法时,如果子类中有该方法,那么执行, 如果子类中没有该方法,则向上查找父类中的方法执行
4.4 方法继承的注意事项
-
类与类的继承, 只支持单继承,不支持多继承
-
类与类的继承,支持多层继承
//一个类文件中要声明多个类,那么只能有一个类被public修饰,而且该类的名字和类文件的名字要保持一致
public class Test {
public static void main(String[] args) {
E e = new E();
e.show();
}
}
class A{
public void show(){
System.out.println("aaaa");
}
}
class B extends A{
public void msg(){
System.out.println("bbbb");
}
}
//单继承
class C extends A{
}
/*
报错,不支持多继承
class D extends A,B{
}*/
class E extends B{
}
五. 继承中的构造器
5.1 前提
在继承中,构造方法是不存在继承的,也就是说,子类不能继承父类的构造方法
5.2 子类中提供自己的构造方法
//定义父类,用于抽取共性内容
public class Person {
private String name;
private int age;
public Person() {
System.out.println("你大爷...");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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 class Teacher extends Person {
private String subject;//学科
public Teacher(){
//super();//调用父类的空参构造
//注意: 如果子类的构造方法没有手动的通过super()调用父类的构造方法,那么子类构造方法第一行隐藏了一个super()
}
public Teacher(String name,int age,String subject){
//this.name = name; 报错,因为这两个成员变量在父类中私有了
//this.age = age;
//super关键字: 父类引用, 可以使用super关键字调用父类的构造方法,也可以调用父类的成员方法
super(name,age);
this.subject = subject;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}
public class Test {
public static void main(String[] args) {
//Teacher t = new Teacher("马老师",18);
Teacher t = new Teacher("马老师",18,"人体动力学...");
System.out.println(t.getSubject()+","+t.getName()+","+t.getAge());
Teacher t2 = new Teacher();
}
}
5.3 super和this
可以使用super访问父类的内容
可以使用this访问当前类的内容
public class Teacher extends Person {
private String subject;//学科
public Teacher(){
//super();//调用父类的空参构造
//注意: 如果子类的构造方法没有手动的通过super()调用父类的构造方法,那么子类构造方法第一行隐藏了一个super()
}
public Teacher(String name,int age,String subject){
//this.name = name; 报错,因为这两个成员变量在父类中私有了
//this.age = age;
//super关键字: 父类引用, 可以使用super关键字调用父类的构造方法,也可以调用父类的成员方法
super(name,age);
this.subject = subject;
}
public Teacher(String name){
this();//调用当前类的空参构造
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public void deSe(){
System.out.println("摇头晃脑");
}
//反抗
public void fanKang(){
super.daErZi();//super.和this.可以加可以不加,但是建议加,因为可以提高代码的阅读性
this.deSe();
System.out.println("谁打我,我干谁....");
}
}
5.4 综合案例
/*
需求:
1.定义一个员工类,
其中有如下属性:
姓名,年龄,岗位
其中有如下行为:
工作
2.定义一个主管类,
其中有如下属性:
姓名,年龄,岗位,司龄
其中有如下行为:
工作,汇报
3.定义一个经理类:
其中有如下属性:
姓名,年龄,岗位,区域
其中有如下行为:
工作,指定战略
注意: 普通员工的工作内容: 简单工作, 主管类的工作内容: 复杂工作 经理类的工作内容: 统筹工作
4.在测试类中分别创建员工类的,主管类的对象和经理类的对象进行调用方法测试
*/
//员工类
public class Employee {
private String name;//姓名
private int age;//年龄
private String post;//岗位
public Employee() {
}
public Employee(String name, int age, String post) {
this.name = name;
this.age = age;
this.post = post;
}
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 String getPost() {
return post;
}
public void setPost(String post) {
this.post = post;
}
//工作的方法
public void work(){
System.out.println("简单工作~");
}
}
//主管类
public class Manager extends Employee{
private int servingAge;//司龄
public Manager() {
}
public Manager(String name, int age, String post, int servingAge) {
super(name, age, post);
this.servingAge = servingAge;
}
public int getServingAge() {
return servingAge;
}
public void setServingAge(int servingAge) {
this.servingAge = servingAge;
}
//重写父类的work方法
@Override
public void work() {
System.out.println("复杂工作");
}
//汇报
public void report(){
System.out.println("阅读汇报");
}
}
//经理类
public class Leader extends Employee{
private String area;//区域
public Leader() {
}
public Leader(String name, int age, String post, String area) {
super(name, age, post);
this.area = area;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
//重写父类的work方法
@Override
public void work() {
System.out.println("统筹工作");
}
//指定战略
public void plan(){
System.out.println("计划");
}
}
public class Test {
/*
需求:
1.定义一个员工类,
其中有如下属性:
姓名,年龄,岗位
其中有如下行为:
工作
2.定义一个主管类,
其中有如下属性:
姓名,年龄,岗位,司龄
其中有如下行为:
工作,汇报
3.定义一个经理类:
其中有如下属性:
姓名,年龄,岗位,区域
其中有如下行为:
工作,指定战略
注意: 普通员工的工作内容: 简单工作, 主管类的工作内容: 复杂工作 经理类的工作内容: 统筹工作
4.在测试类中分别创建员工类的,主管类的对象和经理类的对象进行调用方法测试
*/
public static void main(String[] args) {
Employee e = new Employee("王老师",18,"讲师");
e.work();
System.out.println(e.getName()+","+e.getAge()+","+e.getPost());
System.out.println("==============================================");
Manager m = new Manager("张三",19,"内勤主管",3);
m.work();
m.report();
System.out.println(m.getName()+","+m.getAge()+","+m.getPost()+","+m.getServingAge());
System.out.println("==================================================");
Leader l = new Leader("李四",20,"销售经理","华东区");
l.work();
l.plan();
System.out.println(l.getName()+","+l.getAge()+","+l.getPost()+","+l.getArea());
}
}
六. 抽象类概述
6.1 概念
不具体的类, 被abstract关键字修饰的类
6.2 抽象方法
不具体的方法, 被abstract修饰的方法, 没有方法体
6.3 前提
定义某一个方法时,并不知道该方法的具体实现方案, 那么此时需要把该方法定义成抽象方法
//抽取cat类和dog类中共性的内容
public class Animal {
public void sleep(){
System.out.println("睡觉觉~");
}
public void drink(){
System.out.println("喝水水~");
}
//吃
//定义动物的吃的方法时: 1.动物都有吃的行为, 2.不知道这个行为的具体方案
public void eat(){
System.out.println("吃食物...");
}
}
6.4 抽象方法的定义
格式:
权限修饰符 abstract 返回值类型 方法名(参数列表);
注意:
抽象方法所在的类,必须是抽象类,也就是必须被abstract修饰
//抽取cat类和dog类中共性的内容
//如果一个类中包含了抽象方法,那么该类必须是抽象类
public abstract class Animal {
public void sleep(){
System.out.println("睡觉觉~");
}
public void drink(){
System.out.println("喝水水~");
}
//吃
//定义动物的吃的方法时: 1.动物都有吃的行为, 2.不知道这个行为的具体方案
//如果一个方法没有方法体,那么该方法必须被abstract修饰,该方法就是一个抽象方法
public abstract void eat();
}
6.5 抽象类使用
1.如果一个类是抽象的,那么该类不能被创建对象
2.如果要使用抽象类,必须定义子类继承抽象类,通过使用子类的方式,从而间接的使用当前抽象类
2.1 子类要么是抽象的,被abstract修饰
2.2 子类要么实现父类的所有的抽象方法
//快速实现父类中所有的抽象方法, 光标放到报错的地方,alt+enter
public /*abstract*/ class Sheep extends Animal{
@Override
public void eat() {
System.out.println("吃草草~");
}
}
public class Test {
public static void main(String[] args) {
//Animal a = new Animal();
Sheep s = new Sheep();
s.eat();
s.drink();
}
}
七.抽象类的注意事项及模版设计模式
7.1 抽象类的注意事项
如果一个类中,没有抽象方法,那么这个类,只要被abstract修饰,它就是一个抽象类
7.2 模版设计模式
设计模式: 是前人总结出来的针对一类问题的通用解决方案
java中的设计模式: 23种
单例设计模式, 多例设计模式,装饰者设计模式, 观察者设计模式, 责任链设计模式, 模板设计模式,代理设计模式.......
模版设计模式:
解决的问题: 大部分内容一样,少部分内容有差异
使用:
1.设计模板,规定通用的内容
2.继承模板,书写差异的内容
需求:
写作文:
<我的爸爸>
张三: <我的爸爸> 我的爸爸真好,给我买零食.... 啊,这就是我的爸爸 李四: <我的爸爸> 我的爸爸是大坏蛋,不陪我... 啊,这就是我的爸爸
//设计模板
public abstract class WriteArticle {
//写作文
public void write(){
System.out.println(" <我的爸爸> ");
writeMajor();
System.out.println("啊,这就是我的爸爸...");
}
//定义一个写正文的方法
public abstract void writeMajor();
}
//继承模版
public class XiaoMing extends WriteArticle{
//写正文
@Override
public void writeMajor() {
System.out.println("我的爸爸今天带我去公园, 走着走着走累了, 骑自行车载我, 不小心,我的脚卡到了轮胎里, 我哭的不行不行的,我越哭,他越骑....最后站起来蹬...");
}
}
//测试
public class Test {
public static void main(String[] args) {
//让小明写作文
XiaoMing xm = new XiaoMing();
xm.write();
}
}
八. static关键字
8.1 概念
关键字,静态的意思, 如果一个类中的成员被static关键字修饰,那么该成员属于类, 被当前类的多个对象共享
//学校类
public class School {
//如果成员被static修饰,那么该成员属于类,当前成员会被当前类的多个对象共享
static String name;//学校的名称
String address;//学校的地址
}
public class Test {
public static void main(String[] args) {
School s1 = new School();
s1.name = "衡水一中";
s1.address = "衡水";
System.out.println(s1.name);
System.out.println(s1.address);
System.out.println("===============================");
School s2 = new School();
s2.name="清华附中";
s2.address="清华路";
System.out.println(s2.name);
System.out.println(s2.address);
System.out.println("=======注意观察=======");
System.out.println(s1.name);
System.out.println(s1.address);
}
}
8.2 静态成员访问方式
可以使用类名方法,也可以是使用对象名访问,但是推荐使用类名
public class Test2 {
public static void main(String[] args) {
//推荐使用类名访问
School.name = "北京大学";
School s = new School();
s.name = "清华大学";
}
}
8.3 static修饰成员方法
如果static修饰成员方法,那么该方法属于类, 建议使用类名调用
//学校类
public class School {
//如果成员被static修饰,那么该成员属于类,当前成员会被当前类的多个对象共享
static String name;//学校的名称
String address;//学校的地址
public static void show(){
System.out.println("我是最牛逼的学校...");
}
}
public class Test2 {
public static void main(String[] args) {
//推荐使用类名访问
School.name = "北京大学";
School s = new School();
s.name = "清华大学";
//推荐使用类名调用
School.show();
s.show();
}
}
8.4 static静态代码块
格式:
static{
写代码
}
执行时机:
随着类的加载而执行,并且一次程序的运行过程中,只执行一次
作用:
1. 可以给静态变量赋值 2. 预先加载内容
public class A {
private static String name;
//只执行一次
static{
//name在某个文件中存储着, 读取文件的内容,把读取到的内容赋值给name属性
System.out.println("静态代码块执行了");
}
}
public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
}
}
8.5 静态的访问规则
静态的成员属于类, 非静态的成员属于对象, 类先于对象存在, 静态成员先于非静态成员存在!
1.静态里面只能访问静态的成员!
2.非静态里面可以访问静态的成员,也可以访问非静态的成员!
public class A {
//静态变量
static String name;
//非静态变量
int age;
static{
System.out.println(name);
//System.out.println(age);
}
//静态方法
public static void show(){
//静态中只能访问静态
System.out.println(name);
//静态中不能访问非静态
//System.out.println(age); 报错
}
//非静态方法
public void message(){
//非静态中都可以访问
System.out.println(name);
System.out.println(age);
}
}
8.6 静态的应用场景
静态属于类,所以没有对象也可以访问这些静态的内容, 在开发中,一般情况下,我们的工具类(只提供方法,不提供成员变量)中的方法一般都会设计成静态的!
public class Test {
public static void main(String[] args) {
//Math: jdk提供的数学工具类
//求绝对值
System.out.println(Math.abs(-2));
System.out.println(Math.max(2, 3));
System.out.println(Math.pow(2, 3));
}
}
九. final关键字
9.1概念
是一个关键字, 被final修饰的内容,将不能发生改变
9.2 使用
-
final修饰类
当前的类不能被其他类继承
-
final修饰方法
当前的方法不能被子类重写
-
final修饰变量
该变量只能赋值一次
public class Test {
}
//如果一个类被final修饰,则不能被继承
final class A{
}
class B /*extends A*/{
}
class C{
public void show(){
}
//该方法不能被重写
public final void msg(){
}
}
class D extends C{
@Override
public void show() {
System.out.println("aaaa");
}
/*public final void msg(){
}*/
}
class E{
//如果final修饰成员变量,该成员变量只能赋值一次
//如果final修饰成员变量,那么定义该成员变量的同时,需要给改成员变量赋值
//被final修饰的变量,称为常量
final String name = "阿三";
public void changeName(){
//name = "小四"; 报错
}
}
十. 接口的概述
10.1 概念
接口: 规范
java代码中的接口:用于规定实现类中必须有哪些内容
10.2 格式
interface 接口名{
常量;
抽象方法;
}
十一. 接口的定义和使用
接口不能直接new对象,必须通过实现类间接的使用
如果一个类要实现某个接口: class 类名 implements 接口名{}
//游泳的接口
public interface Swimming {
//常量: 接口中的成员变量默认被 public static final
//某个内容是灰色: 1.该内容内有被使用 2.该内容可以不写(默认值)
//给常量起名字时: 使用大写,如果是多个单词,那么用_连接
/*public static final */String ADDRESS = "水利局";
//抽象方法 接口中的方法,默认被public abstract修饰
/*public abstract*/ void show();
void swim();
}
public class Dog implements Swimming{
@Override
public void show() {
System.out.println("我是天下最美丽的狗....");
}
@Override
public void swim() {
System.out.println("狗刨式游泳....");
}
}
public class Sheep implements Swimming{
@Override
public void show() {
System.out.println("我是天下最帅的洋洋...");
}
@Override
public void swim() {
System.out.println("仰泳....");
}
}
public class Test {
public static void main(String[] args) {
//接口中的常量推荐使用接口名访问
System.out.println(Swimming.ADDRESS);
//创建一个接口对象使用 接口不能直接创建对象
//Swimming s = new Swimming();
Dog d = new Dog();
d.swim();
d.show();
//System.out.println(d.ADDRESS);
System.out.println("========");
Sheep s = new Sheep();
s.swim();
s.show();
//System.out.println(s.ADDRESS);
}
}
十二. 新版本的jdk中的接口的内容升级
在jdk1.7及以前, 接口中只有常量和抽象方法
在jdk1.8版本中,新增了默认方法和静态方法
在jdk1.9版本中,新增了私有方法
12.1 默认方法
使用添加抽象方法的方式,升级接口,不得不修改该接口的实现类,比较麻烦
格式:
public default 返回值类型 方法名(){
方法体;
return 返回值;
}
//游泳的接口
public interface Swimming {
//常量: 接口中的成员变量默认被 public static final
//某个内容是灰色: 1.该内容内有被使用 2.该内容可以不写(默认值)
//给常量起名字时: 使用大写,如果是多个单词,那么用_连接
/*public static final */String ADDRESS = "水利局";
//抽象方法 接口中的方法,默认被public abstract修饰
/*public abstract*/ void show();
void swim();
//void shaiGan();
//这个默认方法,会被所有的实现类继承,子类可以重写,也可以不重写
public default void shiaGan(){
System.out.println("在太阳底下晒干...");
}
}
public class Sheep implements Swimming{
@Override
public void show() {
System.out.println("我是天下最帅的洋洋...");
}
@Override
public void swim() {
System.out.println("仰泳....");
}
}
public class Dog implements Swimming{
@Override
public void show() {
System.out.println("我是天下最美丽的狗....");
}
@Override
public void swim() {
System.out.println("狗刨式游泳....");
}
@Override
public void shiaGan() {
System.out.println("在浴霸底下晒干...");
}
}
public class Test {
public static void main(String[] args) {
//接口中的常量推荐使用接口名访问
System.out.println(Swimming.ADDRESS);
//创建一个接口对象使用 接口不能直接创建对象
//Swimming s = new Swimming();
Dog d = new Dog();
d.swim();
d.show();
d.shiaGan();
//System.out.println(d.ADDRESS);
System.out.println("========");
Sheep s = new Sheep();
s.swim();
s.show();
s.shiaGan();
//System.out.println(s.ADDRESS);
}
}
12.2 私有方法
用于解决多个默认方法中有共性代码的问题
格式:
private 返回值类型 方法名(){
方法体;
return 返回值;
}
//游泳的接口
public interface Swimming {
//常量: 接口中的成员变量默认被 public static final
//某个内容是灰色: 1.该内容内有被使用 2.该内容可以不写(默认值)
//给常量起名字时: 使用大写,如果是多个单词,那么用_连接
/*public static final */String ADDRESS = "水利局";
//抽象方法 接口中的方法,默认被public abstract修饰
/*public abstract*/ void show();
void swim();
//void shaiGan();
//这个默认方法,会被所有的实现类继承,子类可以重写,也可以不重写
public default void shiaGan(){
preWork();
System.out.println("在太阳底下晒干...");
}
public default void fengGan(){
preWork();
System.out.println("在吹风机下风干...");
}
//私有方法,用于解决多个默认方法有共性代码的问题
private void preWork(){
System.out.println("先走出泳池");
System.out.println("再穿上裤子");
}
}
12.3 静态方法
jdk1.8及以前, 要使用接口,必须借助于实现类使用.为了让接口可以脱离实现类单独使用,因此jdk1.9新增了静态方法
格式:
public static 返回值类型 方法名(参数列表){
方法体;
return 返回值;
}
//游泳的接口
public interface Swimming {
//常量: 接口中的成员变量默认被 public static final
//某个内容是灰色: 1.该内容内有被使用 2.该内容可以不写(默认值)
//给常量起名字时: 使用大写,如果是多个单词,那么用_连接
/*public static final */String ADDRESS = "水利局";
//抽象方法 接口中的方法,默认被public abstract修饰
/*public abstract*/ void show();
void swim();
//void shaiGan();
//这个默认方法,会被所有的实现类继承,子类可以重写,也可以不重写
public default void shiaGan(){
preWork();
System.out.println("在太阳底下晒干...");
}
public default void fengGan(){
preWork();
System.out.println("在吹风机下风干...");
}
//私有方法,用于解决多个默认方法有共性代码的问题
private void preWork(){
System.out.println("先走出泳池");
System.out.println("再穿上裤子");
}
//多人游泳
public static void multiSwim(){
System.out.println("多人游泳...");
}
}
public class Test {
public static void main(String[] args) {
//接口中的常量推荐使用接口名访问
System.out.println(Swimming.ADDRESS);
//创建一个接口对象使用 接口不能直接创建对象
//Swimming s = new Swimming();
Dog d = new Dog();
d.swim();
d.show();
d.shiaGan();
//System.out.println(d.ADDRESS);
System.out.println("========");
Sheep s = new Sheep();
s.swim();
s.show();
s.shiaGan();
//System.out.println(s.ADDRESS);
//静态方法可以被接口名直接调用
Swimming.multiSwim();
}
}
十三. 接口和抽象类的异同点
抽象类:
既有常规方法,又有抽象方法
接口:
一般都是抽象方法
类与类的关系:
1. 类与类之间只能单继承 2. 支持多层继承接口与接口的关系:
1. 接口与接口之间支持多继承 2. 支持多层继承类与接口的关系:
一个类可以同时继承另外一个类,并实现多个接口
public class Test {
}
interface A{
}
interface B{
}
//多继承
interface C extends A,B{
}
interface D extends C{
}
//多层继承
interface E extends D{
}
class F {
}
//一个类可以继承其他类的同时实现多个接口
class G extends F implements A,B{
}
十四.综合案例
需求: 定义一个接口,需要有一个行为: 闹钟 定义一个接口,需要有一个行为: 看视频 定义一个类(手机),需要有如下内容: 1.有属性: 品牌,颜色,价格 2.有行为: 打电话,发短信 定义一个苹果手机类,需要有如下内容: 1.有属性: 品牌,颜色,价格 2.有行为: 打电话,发短信,自动上报定位, 闹钟(参照接口) 定义一个华为手机类,需要有如下内容: 1.有属性: 品牌,颜色,价格 2.有行为: 打电话,发短信,卫星通话, 看视频(参照接口) 定义测试类: 创建苹果手机和华为手机调用方法测试
//闹钟接口
public interface Alarming {
//闹钟行为
void alarm();
}
//视频
public interface Video {
//看视频
void watchVideo();
}
public class Phone {
private String brand;//品牌
private String color;//颜色
private double price;//价格
public Phone() {
}
public Phone(String brand, String color, double price) {
this.brand = brand;
this.color = color;
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
//打电话
public void call(){
System.out.println("打电话...");
}
//发短信
public void message(){
System.out.println("发短信...");
}
}
//苹果手机类,继承了手机类,复用手机类中的内容
public class IPhone extends Phone implements Alarming{
//构造方法
public IPhone() {
}
public IPhone(String brand, String color, double price) {
super(brand, color, price);
}
//自动上报定位
public void reportLocation(){
System.out.println("24小时上报位置...");
}
//闹钟行为
@Override
public void alarm() {
System.out.println("叮铃铃...");
}
}
//华为手机类
public class HuaWei extends Phone implements Video {
//构造方法
public HuaWei() {
}
public HuaWei(String brand, String color, double price) {
super(brand, color, price);
}
//卫星通话
public void satellite(){
System.out.println("随时随地打电话...");
}
@Override
public void watchVideo() {
System.out.println("空气投影看视频....");
}
}
public class Test {
/*
需求:
定义一个接口,需要有一个行为: 闹钟
定义一个接口,需要有一个行为: 看视频
定义一个类(手机),需要有如下内容:
1.有属性: 品牌,颜色,价格
2.有行为: 打电话,发短信
定义一个苹果手机类,需要有如下内容:
1.有属性: 品牌,颜色,价格
2.有行为: 打电话,发短信,自动上报定位, 闹钟(参照接口)
定义一个华为手机类,需要有如下内容:
1.有属性: 品牌,颜色,价格
2.有行为: 打电话,发短信,卫星通话, 看视频(参照接口)
定义测试类:
创建苹果手机和华为手机调用方法测试
*/
public static void main(String[] args) {
//创建苹果手机对象,调用方法完成测试
IPhone iPhone = new IPhone("苹果","土豪金",999);
iPhone.alarm();
iPhone.reportLocation();
iPhone.call();
iPhone.message();
System.out.println(iPhone.getBrand()+","+iPhone.getColor()+","+iPhone.getPrice());
System.out.println("==================================");
HuaWei huaWei = new HuaWei("华为","天青",19999);
huaWei.satellite();
huaWei.watchVideo();
huaWei.call();
huaWei.message();
System.out.println(huaWei.getBrand()+","+huaWei.getColor()+","+huaWei.getPrice());
}
}
十五. 多态
1.1 概念
同一个对象在不同时刻展现出的不同形态!
1.2 如何判别当前有没有使用多态
有没有存在父引用(父类的引用,父接口的引用)指向子类对象
public abstract class Animal {
//吃
public abstract void eat();
//喝
public void drink(){
System.out.println("喝水水~");
}
}
//继承父类
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼...");
}
}
public class Test {
public static void main(String[] args) {
//多态: 同一个对象在不同时刻,展现出的不同形态
//使用多态: 父引用指向子类对象
Cat c = new Cat();//并没有使用多态
Animal a = c;//使用了多态
}
}
//老师接口
public interface Teacher {
void teach();
}
//工人接口
public interface Worker {
void work();
}
public class Somebody implements Worker,Teacher{
@Override
public void teach() {
System.out.println("教书育人...");
}
@Override
public void work() {
System.out.println("平地起楼...");
}
}
public class Test {
public static void main(String[] args) {
Somebody s = new Somebody();//创建了一个人的对象
Worker w = s;//使用了多态, 展现的形态是工人
Teacher t = s;//使用了多态, 展现的心态是老师
}
}
1.3 多态的好处
可以提高代码的扩展性和灵活性
public abstract class Animal {
//吃
public abstract void eat();
//喝
public void drink(){
System.out.println("喝水水~");
}
}
//继承父类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼...");
}
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("吃骨头...");
}
}
public class Pig extends Animal{
@Override
public void eat() {
System.out.println("啥都吃...");
}
}
public class Test {
public static void main(String[] args) {
Cat c = new Cat();
//feedCat(c);
feedAnimal(c);
Dog d = new Dog();
//feedDog(d);
//feedCat(d); 这里会报错
feedAnimal(d);
Pig p = new Pig();
feedAnimal(p);
}
//定义一个方法,接收一个猫对象,喂猫
public static void feedCat(Cat c){
c.eat();
c.drink();
}
//定义一个方法,接收一个狗对象,喂狗
public static void feedDog(Dog d){
d.eat();
d.drink();
}
//每有一个新的动物, 需要定义一个新的方法来喂这种动物
//可以设计一个方法,喂所有的动物
public static void feedAnimal(Animal a){
a.eat();
a.drink();
}
}
1.4 多态的弊端
使用父类引用无法调用子类特有的内容
注意:
在多态的调用中, 编译看左边(左边的类中有没有该方法), 运行看右边
public abstract class Animal {
//吃
public abstract void eat();
//喝
public void drink(){
System.out.println("喝水水~");
}
}
//继承父类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼...");
}
//抓老鼠
public void catchMouse(){
System.out.println("抓老鼠");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("吃骨头...");
}
//看门
public void watchDoor(){
System.out.println("看门...");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Cat();
a.eat();
a.drink();
//a.catchMouse();//会报错 编译看左边,而Animal类中并没有catchMouse方法
//需要把父类引用转换成子类引用才可以调用子类特有的内容
/*
引用类型数据的转换:
向上转型: 把低类型的引用转换成高类型的引用
Dog d = new Dog();
Animal a1 = d;
向下转型: 把高类型的引用转换成低类型的引用
低类型 变量 = (低类型)高类型的变量;
*/
Cat c = (Cat) a;
c.catchMouse();
}
}
public class Test2 {
public static void main(String[] args) {
Cat c = new Cat();
useAnimal(c);
Dog d = new Dog();
useAnimal(d);
}
//定义一个方法,使用动物
public static void useAnimal(Animal a){
a.eat();
a.drink();
//向下转型有报错的风险 ClassCastException(类型转换异常)
// instanceof 引用名 instanceof 类名 : 判断当前引用指向的对象是不是指定类的对象
if (a instanceof Cat){
Cat c = (Cat) a;
c.catchMouse();
}
}
}
十六. 内部类
1.1 概念
定义到某个类中的其他类,把它称之为内部类
1.2 分类
成员内部类: 定义到类的成员位置的类
public class Person {
//成员内部类
public class Heart{
}
}
局部内部类: 定义到方法中的类
public class Person {
public void show() {
//局部内部类,不能有权限修饰符
class A {
}
}
//成员内部类
public class Heart {
}
}
匿名[局部]内部类: 定义到方法中的,没有名字的类
匿名内部类及其使用格式:
new 父类名/接口名(){
//类的内容
}
public abstract class Animal {
//吃
public abstract void eat();
//喝
public void drink(){
System.out.println("喝水水~");
}
}
//继承父类
/*
public: 公共的,谁都能访问呢
class: 定义的是一个类
Cat: 类名: 为了让别人可以通过该名字反复的使用该名字所代表的内容
extends Animal: 继承父类, 规定子类中必须有什么内容
{}: 指定类的内容
*/
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼...");
}
}
public class Test {
public static void main(String[] args) {
//创建Cat类的对象,并调用方法使用
Animal a1 = new Cat();
a1.eat();
//使用匿名内部类的方式,创建一个动物对象
/*
new 父类名/接口名(){
//内容
}
*/
/*
new: 申请内存,调用构造方法创建对象
Animal: 用于规定匿名内部类中必须有什么内容
(): 调用匿名内部类的空参构造创建对象
{}: 指定类的内容
*/
Animal a2 = new Animal(){
@Override
public void eat() {
System.out.println("吃草草~");
}
};
a2.eat();
}
}
1.3 匿名内部类和外部类的区别
public class Test {
public static void main(String[] args) {
//创建Cat类的对象,并调用方法使用
Animal a1 = new Cat();
a1.eat();
//使用匿名内部类的方式,创建一个动物对象
/*
new 父类名/接口名(){
//内容
}
*/
/*
new: 申请内存,调用构造方法创建对象
Animal: 用于规定匿名内部类中必须有什么内容
(): 调用匿名内部类的空参构造创建对象
{}: 指定类的内容
*/
Animal a2 = new Animal(){
@Override
public void eat() {
System.out.println("吃草草~");
}
};
a2.eat();
//使用匿名内部类的方式创建另外一个对象
//注意: 使用匿名内部类,定义类的同时可以根据该类创建一个对象,没有办法重复使用
Animal a3 = new Animal() {
@Override
public void eat() {
System.out.println("吃草草~");
}
};
a3.eat();
/*
匿名内部类和传统外部类的区别:
匿名局部内部类:
定义类的同时可以创建一个该类的对象
无需要单独创建文件
内部类在项目编译完毕后,在jvm运行过程中,在jvm内部进行编译,不存在.class文件
外部类:
可以根据该类创建无数个对象
每定义一个类,需要创建一个新的文件
外部类在项目编译完毕后,存在.class文件
使用场景:
如果某个类只创建一个对象,建议使用匿名内部类
如果某个类要反复创建对象, 建议使用外部类
*/
}
}
1.4 匿名内部类的常见使用方式
在传递参数的时候使用
//游泳接口
public interface Swimming {
void swim();
}
public class Sheep implements Swimming{
@Override
public void swim() {
System.out.println("仰泳...");
}
}
public class Test {
//主方法
public static void main(String[] args) {
//调用method方法
//Swimming接口的实现类对象
Swimming sheep = new Sheep();
method(sheep);
//匿名内部类的方式
Swimming frog = new Swimming() {
@Override
public void swim() {
System.out.println("蛙泳...");
}
};
//method(frog);
method(new Swimming() {
@Override
public void swim() {
System.out.println("蛙泳...");
}
});
//匿名内部类最常用的使用方式
method(new Swimming() {
@Override
public void swim() {
System.out.println("狗刨...");
}
});
}
//定义一个方法, 接收一个会游泳的生物,让他游泳
public static void method(Swimming s) {
s.swim();
}
}