2-java面向对象
文章目录
- 常识
- 面向对象和面向过程
- 对象的创建和调用
- 对象在内存中的储存
- 构造方法
- this和super
- 重载和重写
- 方法的重写
- 方法的重载
- 面向对象的三大特征
- 封装
- private关键字
- 测试封装的必要性
- 封装方法
- 继承
- 方法的重写
- 测试继承的使用
- 测试继承里方法的使用
- 测试继承中构造方法的使用
- 测试继承中构造方法的使用
- 测试继承中成员变量的使用
- 多态
- 多态的入门案例
- 多态中各元素的用法
- 向上转型和向下转型
- Static和final
- static静态的
- 静态资源入门案例
- 测试静态方法之间的调用
- final最终的
- final入门案例
- 代码块
- 静态代码块
- 构造代码块
- 局部代码块
- 执行顺序
- 代码块入门案例
- 抽象类
- 抽象方法
- 抽象类入门案例
- 测试抽象类中的构造函数
- 测试抽象类中的资源
- 接口
- 接口的入门案例
- 接口入门案例二
- 测试接口中的构造函数
- 测试接口与类之间的关系
- 接口与类之间的关系总结
- 类与类之间的关系
- 类与接口的关系
- 接口与接口之间的关系
- 抽象类与接口的区别
- 内部类
- 对象的普通创建方式
- 内部类入门案例
- 成员内部类
- 成员内部类被private修饰
- 成员内部类被static修饰
- 局部内部类
- 匿名内部类
- 异常
- 异常的继承结构
- 异常的处理方式
- throws 与 throw 的区别
常识
面向对象和面向过程
- 面向对象和面向过程都是一种编程思想
- 面向对象强调的是结果, 作为指挥者, 去指挥对象完成实物的处理就可以了
- 面向过程强调的是过程, 作为执行者, 每一件事务都要亲力亲为
java: 面向对象的语言
C: 面向过程的语言
对象的创建和调用
通常将类和对象配合使用, 想要使用自己创建的类或者使用底层API提供的类, 必须要创建对象来调用这个类和类中的方法
- 方法格式:
修饰词 返回值 方法名 (参数列表) {方法体}
public void call() {System.out.println("正在打电话");}
- 创建对象格式:
类名 对象名 = new 类名()
Phone p = new Phone();
- 调用对象的方法: 对象名.方法()
p.call();
p.message();
对象在内存中的储存
java把内存分为五大区域, 重点关注栈和堆
- 一般来讲, 局部变量存在栈中, 方法执行完毕内存就被释放
- 对象(new出来的)存在堆中, 对象不再被使用时, 内存才会释放
- 每个堆中的元素都有一个地址值存在栈中
- 对象的属性都有默认值
- TIPS: 栈与队列指的是一种数据的结构
- 栈: 先进后出(FILO – First In Last Out)
- 队列:先进先出(FIFO – First In First Out)
构造方法
- 格式: 修饰符 类名(){ }
- 与类同名且没有返回值类型的参数
- 每一个类中默认会有一个构造方法, 可以不传参数直接创建这个类的对象, 就是用于创建对象
- 如果这个类提供了其他的构造函数,默认的无参构造会被覆盖掉,所以需要手动提供无参构造
- 构造方法也存在重载的现象:无参构造 含参构造 全参构造【创建对象+属性赋值】
this和super
- super
- 代表的是父类对象的引用,我们可以把super看作是Father super = new Father();
- 父类成员变量和子类的变量同名时可以用super.变量名 指定使用父类的变量
- super();表示调用父类的无参构造 super(参数);表示调用父类的对应参数的构造
- this
- this代表的是本类对象的引用,我们可以把this看作是Cat this = new Cat();
- 当本类的成员变量与局部变量同名时,需要使用this.变量名指定本类的成员变量
- this();表示调用本类的无参构造 this(参数);表示调用本类的对应参数的构造
重载和重写
方法的重写
出现在继承中, 如果继承了父类中的一个方法, 但是不想使用这个方法的功能, 可以在子类中重写这个方法
- 返回值类型, 方法名, 参数列表必须与父类中想要重写的方法一致
- 重写方法体里的代码内容
- 重写原则: 两同 两小 一大
- 一大: 子类方法的修饰符范围>=父类方法的修饰符范围–访问控制符
- 两同: 方法名相同,参数列表相同
- 两小:
- 子类返回值类型 <= 父类方法的返回值类型
- 子类方法抛出的异常类型 <= 父类方法抛出的异常类型
注意: 父类方法的返回值类型为void,子类保持一致即可
方法的重载
重载出现在同一个类中, 如果想使用不同参数的同一个方法时, 要使用重载
- 返回值, 方法名相同, 参数列表不同
面向对象的三大特征
封装
将一个事务的属性和行为,(变量和方法)封装成一个类组件
private关键字
通过private关键字修饰后,属性只能在本类中使用,需要对外提供公共的getXxx()与setXxx()
好处:
- 提高安全性
- 提高重用性
测试封装的必要性
package cn.tedu.oop;
/*本类用于测试封装的必要性*/
public class TestPrivate1 {public static void main(String[] args) {//5.创建对象进行测试User u = new User();u.name = "西门庆";System.out.println(u.name);//需要封装属性,如果不封装的话,就可以直接修改属性的值//不需要按照我们预先设置好的方式也能操作//u.money = 1000000;//System.out.println(u.money);u.setMoney(109999);System.out.println(u.queryMoney());}
}
//1.创建一个用户类User
class User{//2.定义用户类的属性public String name;private double money = 10000;//3.提供方法1:可以用来查询当前账户的余额public double queryMoney(){/*后续可以添加权限的校验*/return money;}//4.提供方法2:可以设置当前账户的余额public void setMoney(double money){/*后续可以添加权限的校验*/this.money = money;}
}
封装方法
如果一个方法被private修饰,外界想要调用这个功能,需要在本类中提供一个公共的方法调用这个私有方法
比如封装属性与方法,主要是对资源进行了访问限制,想让外界按照我们提供的方式来使用
继承
继承具有传递性, 创建一个类作为父类, 在创建一个类使用extends关键字继承父类, 就可以使用父类中的所有功能, 还可 以扩展自己的功能
- 私有资源会被继承, 但不能使用, 因为不可见
- 构造方法不能被继承, 构造方法要求方法名与类名相同, 所以不能在子类中出现父类名字的构造方法
- java只允许单继承, 一个子类只能继承一个父类, 一个父类可以有多个子类
方法的重写
如果继承了父类中的一个方法, 但是不想使用这个方法的功能, 可以在子类中重写这个方法
- 返回值类型, 方法名, 参数列表必须与父类中想要重写的方法一致
- 重写方法体里的代码内容
- 重写原则: 两同 两小 一大
- 一大: 子类方法的修饰符范围>=父类方法的修饰符范围–访问控制符
- 两同: 方法名相同,参数列表相同
- 两小:
- 子类返回值类型 <= 父类方法的返回值类型
- 子类方法抛出的异常类型 <= 父类方法抛出的异常类型
注意: 父类方法的返回值类型为void,子类保持一致即可
测试继承的使用
package cn.tedu.Extend;
/**继承*/
public class Extends {public static void main(String[] args) {//创建3个类的对象Animal a = new Animal();Cat c = new Cat();MiaoMiao m = new MiaoMiao();//利用对象调用方法进行测试a.eat();c.eat(); //爸爸类可以使用爷爷类的方法m.eat(); //孙子类可以使用爸爸类继承来的爷爷类的方法/*继承具有传递性,爷爷的功能会传给爸爸,爸爸的功能会传给孙子*/}
}
/*通过Extends管理在建立子类和父类的继承关系,格式:子类 extends 父类
* Java只支持单继承,一个子类只能有一个父类,但是一个父类可以有多个子类*/
//爷爷类
class Animal {// 创建爷爷类的方法public void eat() {System.out.println("小动物Animal吃啥都行~");}
}
//爸爸类,与Animal建立继承关系
/*继承是is a的关系,比如:小猫是小动物,MiaoMiao是一只小猫
* 继承要求子类必须是父类的一种下属类型,依赖性非常强,强耦合*/
class Cat extends Animal{//定义属性--成员变量int a = 10; //普通资源private int b = 100; //私有资源
}
//孙子类,与Cat建立继承关系
class MiaoMiao extends Cat{/*子类可以拥有自己独有的方法,实现了功能的扩展*///定义孙子独有的方法public void studyJava() {/*子类继承了父类以后,可以使用父类的非私有资源* 这个私有资源是由于子类不可见而不能使用的,不是因为没有继承* 因为子类在继承了父类以后,相当于父类的功能完全复制了一份*/System.out.println("正在学Java");System.out.println(a);
// System.out.println(b);}
}
测试继承里方法的使用
package cn.tedu.Extend;
/**继承中方法的使用*/
/*方法的重写: 继承后,子类对父类的功能不满意,就可以重新写父类的功能
* 重写原则: 两同 两小 一大
* 一大: 子类方法的修饰符范围>=父类方法的修饰符范围--访问控制符
* 两同: 方法名相同,参数列表相同
* 两小: 子类返回值类型 >= 父类方法的返回值类型
* 子类方法抛出的异常类型 >= 父类方法抛出的异常类型
* 注意: 父类方法的返回值类型为void,子类保持一致即可
* 子类不可以重写父类的私有方法,原因不可见*/
public class ExtendsRewriteMethod {public static void main(String[] args) {Father3 f3 = new Father3();Son3 s3 = new Son3();f3.eat();//重写后使用的子类重写的功能s3.eat(); //继承后子类可以使用父类的非私有资源}
}
class Father3{public void eat() {System.out.println("爸爸爱吃饭");}public void play() {System.out.println("爸爸爱放风筝");}
}class Son3 extends Father3 {//拓展功能public void studyJava() {System.out.println("我扩展了Java的功能");}//重写父类中的eat方法@Override/*@Override是一个注解,标记这个方法是一个重写的方法,如果可以加,说明此方法可以重写*/public void eat() {System.out.println("儿子爱吃蔬菜");}
}
测试继承中构造方法的使用
package cn.tedu.Extend;
/**用于测试继承中构造方法的使用*/
/*1.子类创建对象时,默认先调用父类的构造方法
* 2.原因是由于构造函数的第一行默认存在super()--表示调用父类的无参构造
* 3.当父类没有无参构造时,可以通过super(参数)调用父类的其他含参构造
* 4.构造方法不可以被继承,因为语法原因,构造要求与类同名,所以自然不符合要求*/
public class ExtendsConstructionMethod {public static void main(String[] args) {Father2 f2 = new Father2("参数");Son2 s2 = new Son2();}
}class Father2 {//创建父类的无参构造public Father2(){System.out.println("我是Father2的无参构造");}public Father2(String s){System.out.println("我是Father2的"+s);}}class Son2 extends Father2{//子类无参构造方法public Son2() {super("含参构造");System.out.println("我是son2的无参构造");}
}
测试继承中构造方法的使用
package cn.tedu.Extend;
/**用于测试继承中构造方法的使用*/
/*1.子类创建对象时,默认先调用父类的构造方法
* 2.原因是由于构造函数的第一行默认存在super()--表示调用父类的无参构造
* 3.当父类没有无参构造时,可以通过super(参数)调用父类的其他含参构造
* 4.构造方法不可以被继承,因为语法原因,构造要求与类同名,所以自然不符合要求*/
public class ExtendsConstructionMethod {public static void main(String[] args) {Father2 f2 = new Father2("参数");Son2 s2 = new Son2();}
}class Father2 {//创建父类的无参构造public Father2(){System.out.println("我是Father2的无参构造");}public Father2(String s){System.out.println("我是Father2的"+s);}}class Son2 extends Father2{//子类无参构造方法public Son2() {super("含参构造");System.out.println("我是son2的无参构造");}
}
测试继承中成员变量的使用
package cn.tedu.Extend;
/**测试继承中成员变量的使用*/
public class ExtendsSuper {public static void main(String[] args) {Son s = new Son();s.eat();}
}class Father {//定义父类的成员变量int count = 1;int sum = 2;
}class Son extends Father {//定义成员变量int sum = 100;public void eat() {//定义局部变量int sum = 10;System.out.println(sum); //打印局部变量System.out.println(this.sum); //打印成员变量/*在子类中使用父类的sum资源,需要使用Super进行指定*///使用父类的成员变量System.out.println(count); //使用父类不重名的成员变量System.out.println(super.sum); //使用父类重名的成员变量}
}
多态
同一个对象, 不同时刻, 代表的对象不一样, 拥有多种形态
可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,统一调用标准。
多态的前提: 继承+重写
- 父类引用, 指向子类对象
- 编译看左边, 运行看右边
因为引用的父类对象, 在编译的时候只会编译父类里有的资源, 子类自己扩展的功能不会被编译
多态的入门案例
public class Polymorphism {public static void main(String[] args) {Animal a = new Animal();Cat c = new Cat();Dog d = new Dog();a.eat();c.eat();d.eat();/*父类不能调用子类的特有功能*/
// a.play();c.play();d.play();/*3.多态* 口诀1: 父类引用指向子类对象* 解释: 创建出来的子类对象的地址值交给父类类型的引用类型变量来保存*/Animal a2 = new Cat();Animal a3 = new Dog();/*4. 口诀2: 编译看左边,运行看右边* 解释: 必须要父类定义这个方法, 才能通过编译,编译时,把多态对象看做是父类类型* 必须要子类重写这个方法,才能满足多态,运行时实际干活的是子类*/a2.eat();
// a2.play();}}
/*多态的前提: 继承+重写*/
class Animal{public void eat() {System.out.println("小动物Animal吃啥都行");}
}class Cat extends Animal {@Overridepublic void eat() {System.out.println("小猫爱吃小鱼干");}public void play() {System.out.println("小猫cat跳的可高了");}
}class Dog extends Animal {@Overridepublic void eat() {System.out.println("小狗爱吃肉骨头");}public void play() {System.out.println("小狗Dog跑的老快了");}
}
多态中各元素的用法
package cn.tedu.polymorphism;
/**本类用于测试多态中元素的使用*/
public class Demo2 {public static void main(String[] args) {Animal2 a = new Animal2();Dog2 d = new Dog2();//多态对象Animal2 a2 = new Dog2();d.eat();d.play();/*2. 多态中, 成员变量使用的都是父类的*/System.out.println(a2.sum);/*3. 多态中, 成员方法的定义使用的是父类的, 实现(方法体)使用的是子类的*/a2.eat();/*4. 多态中, 如果父子类都有静态重名的方法, 这个不是重写的现象* 所以静态方法调用的还是父类的实现(方法体)*/a2.play();}
}class Animal2 {int sum = 10;public void eat() {System.out.println("吃啥都行");}public static void play() {System.out.println("玩啥都行");}
}
/*1. 多态的前提: 继承+重写*/
class Dog2 extends Animal2{int sum = 20;@Overridepublic void eat() {System.out.println("小狗爱吃肉包子");}/*添加子类的静态方法, 在那个类中写就属于哪个类的资源, 可以直接被类名调用*/public static void play() {System.out.println("小狗爱打滚");}
}
- 成员变量:使用的是父类的
- 成员方法:由于存在重写,所以是父类的声明,子类的方法体
- 静态资源:静态资源属于类资源,是谁的,就返回谁的,而多态把自己看作父类类型,所以使用的是父类的
向上转型和向下转型
- 父类引用指向子类对象: 向上转型(常用) Parent p = new Child();
- 子类引用指向子类对象: 向下转型 Child c = (Child)p;
- 必须要进行强制转型, 把Parent类型的p转成小类型Child
- 就可以使用子类扩展的功能了
Static和final
static静态的
static关键字,可以修饰变量、方法、代码块、内部类,代表是静态的资源
- 静态资源可以通过类名 .直接调用, 因为优先于对象加载, 随着类的加载而加载, 不用创建对象就可以直接通过类名调用
- 静态资源全局被所有对象共享,值只有一份
- 不能与this和super公用, 因为没有对象
- 静态资源只能调用静态资源,非静态资源不做限制,静态与非静态都能使用
静态资源入门案例
package cn.tedu.Static;
/**静态的入门案例*/
public class Static {public static void main(String[] args) {/*3.静态资源可以通过类名直接调用* 原因:静态资源优先于对象进行加载,随着类的加载而加载的* 比对象优先加载入内存,没创建对象时也可以通过类名直接调用*/System.out.println(Student.name);Student.study();//创建对象Student s = new Student();System.out.println(s.sno);System.out.println(s.name);s.study();s.name = "金角大王";System.out.println(s.name);//7.创建多个对象进行测试/*4.静态资源被全局所有对象共享,只能有一个值*/Student s2 = new Student();System.out.println(s2.name);System.out.println(Student.name);s2.name = "银角大王";System.out.println(s.name);System.out.println(s2.name);System.out.println(Student.name);}
}class Student {/*1.可以通过static关键字来修饰成员变量与方法,修饰方法一般写在权限修饰符之后* 2.被static修饰的资源称作静态资源*///定义属性int sno;//学号static String name;//姓名//定义方法public static void study() {System.out.println("学Java呢");}public void speak() {System.out.println("爱就大声说出来");}
}
测试静态方法之间的调用
package cn.tedu.Static;
/**测试静态的调用关系*/
/*总结:
* 1. 普通资源可以调用普通资源,也可以调用静态资源
* 2. 静态资源只能调用静态资源,不能调用普通资源*/
public class StaticTransfer {}class Teacher {String name;public void teach() {System.out.println("正在上课中..");/*1.普通资源可以调用静态资源*/System.out.println(age);ready();}static int age;public static void ready() {System.out.println("正在备课中..");/*静态资源不可以调用非静态资源*/
// System.out.println(name);
// teach();}public static void eat() {System.out.println("正在吃饭中..");/*静态资源能否调用静态资源*/System.out.println(age);ready();}
}
final最终的
final关键字, 表示最终的, 用来修饰类 方法 属性
- 修饰类是最终类, 不能被继承, 叶子节点
- 修饰方法代表最终实现, 不能被重写
- 修饰属性是常量, 值不能修改
- 定义常量必须赋值, 否则报错
final入门案例
package cn.tedu.Final;
/**用于final的学习*/
public class Final {public static void main(String[] args) {Son s = new Son();
// s.name = "干饭人"; //会报错,因为常量的值不能被修改}
}/*1. final表示最终, 表示用来修饰类* 但是被final修饰的类是最终类, 无法被继承* 没有子类, 他自己就是叶子节点*/
//测试类被final修饰
//final class Father { }class Father {/*2. final可以用来修饰方法, 被final修饰的方法是这个方法的最终实现* 不可以被重写*/
// final public void work() {// System.out.println("在车间上班..");
// }public void work() {System.out.println("在车间上班..");}
}
class Son extends Father {/*3.final可以用来修饰"变量", 其实不是"变量", 而是常量* 常量的值是不可以被更改的* 定义常量时必须要同时赋值, 不能先定义再赋值, 不符合语法*/final String name = "打工人";
// final int a; 定义常量时必须要同时赋值, 不能先定义再赋值, 不符合语法//重写父类work方法@Overridepublic void work() {System.out.println("在格子间上班..");}
}
代码块
静态代码块
- 位置: 类里方法外
- 执行时机: 属于静态资源, 随着类的加载而加载, 优先于对象加载并且只加载一次
- 作用: 用于加载需要第一时间就加载, 并且只加载一次的资源
构造代码块
- 位置: 类里方法外
- 执行时机: 每次创建对象时被触发, 并且优先于构造方法执行
- 作用: 用于提取所有构造方法的共性功能
局部代码块
- 位置: 方法里
- 执行时机: 执行局部代码块所在的方法时才会执行
- 作用: 用于限制变量的作用范围
执行顺序
静态代码块->构造代码块->构造方法(对象创建成功)->局部代码块
代码块入门案例
package cn.tedu.Static;
/**静态代码块*/
/*执行顺序:
* 静态代码块->构造代码块->构造方法(对象创建成功)->局部代码块*/
public class StaticBlock {public static void main(String[] args) {Person p = new Person();Person p2 = new Person();p.play();}
}class Person {//静态代码块/*位置: 类里方法外* 执行时机: 属于静态资源, 随着类的加载而加载, 优先于对象加载并且只加载一次* 作用: 用于加载需要第一时间就加载, 并且只加载一次的资源*/static {System.out.println("我是静态代码块");}//构造代码块/*类里方法外* 每次创建对象时被触发, 并且优先于构造方法执行* 用于提取所有构造方法的共性功能*/{System.out.println("我是构造代码块");}//构造方法public Person() {System.out.println("我是无参构造");}//普通方法public void play() {System.out.println("我是一个普通方法");//局部代码块/*方法里* 执行局部代码块所在的方法时才会执行* 用于限制变量的作用范围*/{System.out.println("我是局部代码块");}}
}
抽象类
abstract关键字定义抽象类和抽象方法
- 如果一个类包含了一个抽象方法, 必须要将这个类定义为抽象类
- 抽象类不能被实例化, 必须通过继承, 在子类实现抽象类里的抽象方法
- 当一个类继承了抽象父类,有两种解决方案:
- 变成抽象子类
- 变成普通子类, 或实现抽象父类中的所有抽象方法
- 抽象类有构造方法, 为了子类实现时使用super()创建对象
- 抽象类中的资源:
- 成员变量
- 成员常量
- 普通方法
- 抽象方法
- 构造方法
抽象方法
被abstract修饰的方法是抽象方法, 抽象方法没有方法体
格式: abstract public void 方法名()
抽象类入门案例
package cn.tedu.Abstract;
/**本类用作抽象的入门案例*/
public class Demo {public static void main(String[] args) {/*3.抽象类不可以被实例化--创建对象*/
// new Phone();Phone p = new XM();p.money();p.call();}
}/*1. 被abstract修饰的类是抽象类
* 如果包含了一个抽象方法, 那么这个类必须被声明一个抽象类*/
abstract class Phone {public void call() {System.out.println("正在打电话..");}public void message() {System.out.println("正在发短信..");}//抽象方法/*2. 被abstract修饰的方法是抽象方法, 抽象方法没有方法体*/abstract public void money();abstract public void money2();
}/*4.当一个类继承了抽象父类,有两种解决方案:
* 一: 变成抽象子类
* 二: 变成普通子类, 或实现抽象父类中的所有抽象方法*/
//abstract class XM extends Phone {class XM extends Phone {@Overridepublic void money() {System.out.println("实现父类未实现的方法1");}@Overridepublic void money2() {System.out.println("实现父类未实现的方法2");}
}
测试抽象类中的构造函数
package cn.tedu.Abstract;
/**本类用于测试抽象类中的构造函数*/
/*抽象类有构造方法
* 不是为了自己创建对象使用,而是为了子类创建对象时使用super()*/
public class Demo2 {public static void main(String[] args) {Pig p = new Pig();}
}abstract class Animal {public Animal() {System.out.println("我是Animal类中的构造方法");}
}class Pig extends Animal{public Pig() {super();System.out.println("我是Pig中的无参构造");}
}
测试抽象类中的资源
package cn.tedu.Abstract;
/**本类用于测试抽象类中的成员*/
public class Demo3 {}abstract class Fruit {int sum = 100; //成员变量final String name = "XHR"; //成员常量public void clean() {System.out.println("普通方法");}abstract public void grow(); //抽象方法abstract public void clean2();
}/*如果一个子类继承了一个抽象父类,有两种解决方案
* 一: 自己也是抽象子类
* 二: 作为普通子类, 实现父类中所有的抽象方法*/
class Banana extends Fruit {@Overridepublic void grow() {System.out.println("一串香蕉老沉了");}@Overridepublic void clean2() {System.out.println("香蕉不用洗");}
}
接口
可以当做是一个特殊的抽象类
interface关键字来定义接口
implements关键字与接口建立实现关系, 实现方法与抽象类一样, 必须实现接口中的所有抽象方法
- 接口中全部为抽象方法,没有构造方法
- 一般创建的都是接口实现类的对象, 创建多态对象也可以(不推荐)
- 接口实现类构造方法中的第一行super()调用的是默认继承的顶级父类object中的无参构造
- 接口中没有成员变量, 而是静态常量, 会默认拼接static和final
- 静态的表现: 可以通过接口名直接调用
- 常量的表现: 值不可以被修改, 需要定义的同时赋值
接口的入门案例
- 创建接口的测试
package cn.tedu.Inter;
/**本接口用于创建接口测试*/
/*通过interface关键字来定义接口*/
public interface Inter {/*接口中不可以有普通方法*/
// public void eat(){}/*接口中可以有抽象方法,而且接口中的方法全部为抽象方法*/abstract public void eat();abstract public void play();}
- 创建接口的实现类
package cn.tedu.Inter;
/**本类用作Inter接口的实现类,用于实现Inter接口中定义的方法*/
/*1. 接口实现类通过implements关键字与接口建立实现关系
* 实现方案:
* 一: 抽象子类, 可是不实现/实现部分接口中的抽象方法
* 二: 普通子类, 实现接口中的所有抽象方法*/
//abstract public class InterImpl implements Inter{public class InterImpl implements Inter{@Overridepublic void eat() {System.out.println("吃火锅");}@Overridepublic void play() {System.out.println("玩代码");}
}
- 创建接口实现类对象
package cn.tedu.Inter;
/**本类用作接口功能的测试类*/
public class InterTest {public static void main(String[] args) {Inter i = new InterImpl(); //多态对象i.eat();i.play();/*一般创建的都是接口实现类的对象, 创建多态对象也可以(不推荐)*/InterImpl i2 = new InterImpl(); //接口实现类对象i.eat();i.play();}
}
接口入门案例二
package cn.tedu.Inter2;
/**本类用于面向接口编程--设计老师类*/
/*1.接口是先天设计的结果*/
public class DesignTeacher {public static void main(String[] args) {CGBTeacher c = new CGBTeacher();ACTTeacher a = new ACTTeacher();c.ready();c.teach();a.ready();a.teach();}}//1. 创建Teacher接口-- 提取共性, 形成抽象层, 体现接口, 接口定义的是规则
/*2.通过interface关键字来定义接口*/
interface Teacher {/*3.接口中都是抽象方法, 可以简写, 默认拼接public abstract*///2. 定义接口中的抽象方法void ready();void teach();
}//3. 创建实现类
/*4. 如果实现类需要使用接口的原则,就需要建立实现关系: implements*/
class CGBTeacher implements Teacher {@Overridepublic void ready() {System.out.println("正在备课Java");}@Overridepublic void teach() {System.out.println("正在授课Java");}
}class ACTTeacher implements Teacher {@Overridepublic void ready() {System.out.println("正在备课高手加薪");}@Overridepublic void teach() {System.out.println("正在授课高手加薪");}
}
测试接口中的构造函数
package cn.tedu.Inter2;
/** 本类用于进一步测试接口的使用*/
public class TestUserInter {public static void main(String[] args) {/*如果一个类没有明确指定父类, 那么他的父类就是顶级父类Object* 既然接口实现类实现了接口, 接口中又没有构造方法* 那么接口实现类构造方法中的第一行super()调用的是谁的构造方法?* 答: 使用的是默认继承的顶级父类object中的无参构造*/Inter2Impl i = new Inter2Impl();System.out.println(Inter2.age);}
}interface Inter2 {/*接口中没有构造方法*/
// public Inter2(){}/*接口中没有成员变量* 而是静态常量, 会默认拼接static和final* 静态的表现: 可以通过接口名直接调用* 常量的表现: 值不可以被修改, 需要定义的同时赋值*/int age = 10;/*接口中方法的定义可以简写, 会自动拼接public abstract*/void eat();
}class Inter2Impl implements Inter2 {public Inter2Impl() {System.out.println("我是实现类的无参构造");}@Overridepublic void eat() {System.out.println("吃吃吃");}
}
测试接口与类之间的关系
package cn.tedu.Inter2;/**本类用于测试接口与类之间的复杂关系*//*类与类之间的关系:
* 只能单继承, 单实现
* 构造方法不能被继承
* 子类如果想更改父类的功能,可以重写(两同两小一大)
*
* 接口与类之间的关系:
* 既可以单实现,也可以多实现
* 1. 实现类实现接口,必须去实现接口中的所有抽象方法, 如果有任何一个没有实现, 就要声明成抽象子类
* 2. 创建实现类对象时, 一般使用实现类对象, 而不是多态对象, 因为效果一样
*
* 接口与接口之间的关系:
* 既可以单继承,也可以多继承
* 接口的实现类需要实现继承后的所有抽象方法
*
* 抽象类和接口的区别:
* 1. 抽象类是一个特殊的类, 使用class定义, 特殊在这个类中可以定义没有方法体的方法(抽象方法)
* 2. 接口可以理解为一个特殊的抽象类, 在接口中所有的方法都是抽象方法, 接口不是类, 用interface定义
* 3. 接口中没构造方法, 子类调用的是父类的构造方法
* 4. 抽象类中有构造方法,为了给子类创建对象时调用
* 5. 接口可以多继承,抽象类只能单继承
* 6. 抽象类可以定义普通的成员变量, 接口只能定义静态常量
* 7. 接口与抽象类均不可以实例化/创建对象
* 8. 抽象是后天重构的结果, 接口是先天设计的结果*/
public class Relation {}interface Inter1 {void save(); //保存方法void find(); //查询方法
}interface Inter22 {void update(); //更新方法void delete(); //删除方法
}
/*之前学到: 一个类只能继承父类, 这个是Java中的"单继承"
* 现在: 一个接口可以同时继承多个接口, 叫"多继承"*/
interface Inter3 extends Inter1,Inter22 {}
/*之前学到: 一个类只能有一个父类, 这个是Java中的"单继承"* 现在: 一个类除了可以继承一个父类以外, 还可以同时实现多个接口, 叫"多实现"*/
//class Inter3Impl implements Inter3 {class Inter3Impl implements Inter1,Inter22 {@Overridepublic void save() {System.out.println("正在保存");}@Overridepublic void find() {System.out.println("正在查询");}@Overridepublic void update() {System.out.println("正在修改");}@Overridepublic void delete() {System.out.println("正在删除");}
}
接口与类之间的关系总结
类与类之间的关系
● 继承关系,只支持单继承
○ 比如:class A extends B,A是子类,B是父类,子类具备父类的所有功能
类与接口的关系
- 实现关系,既可以单实现,也可以多实现
- 比如:class A implements Inter1{}
- 比如:class A implements Inter2,Inter3{}
- A是实现类,Inter1,Inter2,Inter3是被实现的接口
- 注意1:实现类去实现接口必须实现接口中的所有抽象方法,如果有任何一个没有实现,就得声明成抽象子类
- 注意2:创建实现类对象时,一般使用实现类对象,而不是多态对象,因为效果一样
接口与接口之间的关系
- 继承关系,既可以单继承,也可以多继承
- 比如:interface A extends Inter1{}
- 比如:interface A2 extends Inter2,Inter3{}
- A,A2是子接口,Inter1,Inter2,Inter3是被继承的父接口
- 注意: 接口A2的实现类需要实现接口A2继承自Inter2和Inter3的所有抽象方法
抽象类与接口的区别
- 抽象类
- 抽象类是一个特殊的类,使用class定义,特殊在这个类中可以定义没有方法体的方法(抽象方法)
- 抽象类中有构造方法,为了给子类创建对象时调用
- 抽象类只能单继承
- 抽象类不可以实例化/创建对象
- 抽象类可以定义普通的成员变量
- 抽象类是后天重构的结果
- 接口
- 接口可以理解成一个特殊的抽象类,用interface定义, 接口中所有的方法都是抽象方法,接口不是类
- 接口中没有构造方法的,子类调用的是父类的构造方法
- 接口可以多继承
- 接口不可以实例化/创建对象
- 接口只能定义静态常量
- 接口是先天设计的结果
内部类
- 可以把内部类看作是外部类的一个特殊的资源
- 内部类可以直接使用外部类的所有资源,包括私有资源
- 外部类如果想要使用内部类的资源,需要创建内部类的对象才能使用
- 在成员位置的内部类是成员内部类
- 在局部位置的内部类是局部内部类
如果一个类存在的意义就是为指定的另一个类,可以把这个类放入另一个类的内部。
就是把类定义在类的内部的情况就可以形成内部类的形式。
A类中又定义了B类,B类就是内部类,B类可以当做A类的一个成员看待:
对象的普通创建方式
外部类名.内部类名 对象名 = 外部类对象.内部类对象
Outer.Inner oi = new Outer().new Inner();
内部类入门案例
package cn.tedu.innerclass;
/*本类用作测试内部类的入门案例*/
public class TestInner1 {public static void main(String[] args) {//3.创建内部类对象,使用内部类的资源/*外部类名.内部类名 对象名 = 外部类对象.内部类对象*/Outer.Inner oi = new Outer().new Inner();oi.delete();System.out.println(oi.sum);//4.调用外部类的方法--这样是创建了一个外部类的匿名对象,只使用一次new Outer().find();}
}//1.创建外部类 Outer
class Outer{//1.1创建外部类的成员变量String name;private int age;//1.2创建外部类的成员方法public void find(){System.out.println("Outer...find()");//6.测试外部类如何使用内部类的资源//System.out.println(sum);--不能直接使用内部类的属性//delete();--不能直接调用内部类的方法/*外部类如果想要使用内部类的资源,必须先创建内部类对象* 通过内部类对象来调用内部类的资源*/Inner in = new Inner();System.out.println(in.sum);in.delete();}//2.创建内部类Inner--类的特殊成员/*根据内部类位置的不同,分为:成员内部类(类里方法外)、局部内部类(方法里)*/class Inner{//2.1定义内部类的成员变量int sum = 10;//2.2定义内部类的成员方法public void delete(){System.out.println("Inner...delete()");//5.测试内部类是否可以使用外部类的资源/*结论:内部类可以直接使用外部类的资源,私有成员也可以!*/System.out.println(name);System.out.println(age);/*注意:此处测试完毕需要注释掉,否则来回调用* 会抛出异常StackOverFlowException栈溢出异常*///find();}}
}
成员内部类
类里方法外
成员内部类被private修饰
- 被私有化的内部类在main()中是没有办法直接创建其对象的
- 可以在私有内部类所处的外部类中,创建一个公共的方法供外界调用,这个方法用来返回创建好的私有内部类对象
package cn.tedu.innerclass;
/**本类用来测试成员内部类被private修饰*/
public class TestInner2 {public static void main(String[] args) {/**怎么使用内部类Inner2的资源?*///4.创建内部类Inner2对象进行访问//Outer2.Inner2 oi = new Outer2().new Inner2();//oi.eat();/**如果Inner2被private修饰,无法直接创建对象该怎么办?*///7.创建外部类对象,间接访问私有内部类资源new Outer2().getInner2Eat();}
}
//1.创建外部类Outer2
class Outer2{//6.提供外部类公共的方法,在方法内部创建Inner2内部类对象,调用内部类方法public void getInner2Eat() {Inner2 in = new Inner2();//外部类可以访问内部类的私有成员in.eat();}//2.1创建成员内部类Inner2/**成员内部类的位置:类里方法外*///5.成员内部类,被private修饰私有化,无法被外界访问private class Inner2{//3.创建内部类的普通成员方法public void eat() {System.out.println("我是Inner2的eat()");}}
}
成员内部类被static修饰
- 静态内部类可以不创建外部类对象,直接创建静态内部类对象,格式:Outer3.Inner3 oi = new Outer3.Inner3();
- 如果静态内部类中还有静态方法,那么我们可以不创建对象
- 直接通过链式加载的方式调用:Outer3.Inner3.show2();//表示通过外部类名直接找到静态内部类,再找到静态方法
package cn.tedu.innerclass;
/**本类用来测试成员内部类被static修饰*/
public class TestInner3 {public static void main(String[] args) {/**如何访问内部类的show()?*///4.创建内部类对象访问show()//方式一:按照之前的方式,创建内部类对象调用show()//Outer3.Inner3 oi = new Outer3().new Inner3();//oi.show();//方式二:创建匿名内部类对象访问show()//new Outer3().new Inner3().show();/**现象:当内部类被static修饰以后,new Outer3()报错*///6.用static修饰内部类以后,上面的创建语句报错,注释掉//通过外部类的类名创建内部类对象Outer3.Inner3 oi = new Outer3.Inner3();oi.show();//7.匿名的内部类对象调用show()new Outer3.Inner3().show();//9.访问静态内部类中的静态资源--链式加载Outer3.Inner3.show2();}
}//1.创建外部类Outer3
class Outer3{//2.创建成员内部类Inner3//5.内部类被static修饰—并不常用!浪费内存!static class Inner3{//3.定义成员内部类中普通的成员方法public void show() {System.out.println("我是Inner3类的show()");}//8.定义成员内部类的静态成员方法static public void show2() {System.out.println("我是Inner3的show2()");}}
}
局部内部类
- 位置:方法里
- 直接创建外部类对象,调用局部内部类所处的方法,并不会触发局部内部类的功能
- 需要在外部类中创建局部内部类的对象并且进行调用局部内部类的功能,才能触发内部类的功能
package cn.tedu.innerclass;
/**本类用来测试局部内部类*/
public class TestInner4 {public static void main(String[] args) {/**如何使用内部类的资源呢?* 注意:直接调用外部类的show()是无法触发内部类功能的* 需要再外部类中创建内部类对象并且进行调用,才能触发内部类的功能* *///5.创建外部类对象调用show()//7.当在外部类show()中创建局部内部类对象并且进行功能调用后,内部类的功能才能被调用new Outer4().show();}
}
//1.创建外部类Outer4
class Outer4{//2.创建外部类的成员方法public void show() {//3.创建局部内部类Inner4—不太常用!!!/**位置:局部内部类的位置在方法里*/class Inner4{//4.创建局部内部类的普通属性与方法String name;int age;public void eat() {System.out.println("我是Inner4的eat()");}}/**如何使用局部内部类的资源?*///6.在show()里创建内部类对象Inner4 in = new Inner4();in.eat();System.out.println(in.name);System.out.println(in.age);}
}
匿名内部类
- 位置:可运行代码中,比如 main()中
- 匿名内部类通常与匿名对象【没有名字的对象】一起使用
- 格式:new Inter1(){ 我这个大括号其实是一个匿名内部类,我来实现方法 }.eat();
- 如果只是想使用一次接口/抽象类的某个功能,可以使用匿名内部类
- 匿名内部类+匿名对象的功能:创建实现类+实现方法+方法功能的一次调用【功能三合一】
package cn.tedu.innerclass;
/*本类用于测试匿名内部类
* 匿名内部类没有名字,通常与匿名对象结合在一起使用*/
public class TestInner5 {public static void main(String[] args) {//传统方式:创建接口的实现类+实现类实现接口中的抽象方法+创建实现类对象+通过对象调用方法//3.创建接口一对应的匿名对象与匿名内部类,并调用实现了的方法save()new Inter1(){@Overridepublic void save() {System.out.println("save()...");}@Overridepublic void get() { }}.save();//5.创建抽象类对应的匿名对象与匿名内部类new Inter2(){@Overridepublic void drink() {System.out.println("一人饮酒醉");}}.drink();//7.调用普通类的功能怎么调用?创建匿名对象直接调用new Inter3().powerUp();new Inter3().powerUp();//new了2次,所以是两个匿名对象/*如果想要多次使用实现后的功能,还是要创建普通的对象* 匿名对象只能使用一次,一次只能调用一个功能* 匿名内部类其实就充当了实现类的角色,去实现未实现的抽象方法,只是没有名字而已*/Inter3 in = new Inter3();in.study();in.study();in.study();in.study();in.study();in.study();}
}//1.创建接口
interface Inter1{//2.定义接口中的抽象方法void save();void get();
}
//4.创建抽象类
abstract class Inter2{public void play(){System.out.println("Inter2...play()");}abstract public void drink();
}
//6.创建普通类
class Inter3{public void study(){System.out.println("什么都阻挡不了我想学习赚钱的决心");}public void powerUp(){System.out.println("我们会越来越强的!");}
}
异常
异常的继承结构
异常的处理方式
捕获方式:
抛出方式:
对于不想现在处理或者处理不了的异常可以选择向上抛出
在方法上设置异常的抛出管道: throws 异常类型
例如:void method1 throws Exception1,Exception2,Exception3{ }
throws 与 throw 的区别
throws :
- 用在方法声明处,其后跟着的是异常类的名字
- 表示此方法会抛出异常,需要由本方法的调用者来处理这些异常
- 但是注意:这只是一种可能性,异常不一定会发生
throw :
- 用在方法的内部,其后跟着的是异常对象的名字
- 表示此处抛出异常,由方法体内的语句处理
- 注意:执行throw一定抛出了某种异常
2-java面向对象相关推荐
- java面向对象-------静态初始化块
1.构造方法用于对象的初始化!静态初始化块,用于类的初始化操作,在静态初始化块中不能直接访问非static成员. package java面向对象; /** * 测试静态初始化块 */public c ...
- JAVA面向对象-----final关键字
JAVA面向对象-–final关键字 1:定义静态方法求圆的面积 2:定义静态方法求圆的周长 3:发现方法中有重复的代码,就是PI,圆周率.1:如果需要提高计算精度,就需要修改每个方法中圆周率. 4: ...
- Java学习笔记二十五:Java面向对象的三大特性之多态
Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...
- 12 Java面向对象之多态
JavaSE 基础之十二 12 Java面向对象之多态 ① 多态的概念及分类 多态的概念:对象的多种表现形式和能力 多态的分类 1. 静态多态:在编译期间,程序就能决定调用哪个方法.方法的重载就表现出 ...
- 猫抓老鼠-Java面向对象特点梳理
我们先设计一个猫抓老鼠的小游戏: ⊙猫和老鼠都有名字和体重两种属性,猫有抓老鼠的方法,对应的老鼠则有逃跑的方法. ⊙首先游戏的结果是猫抓住了老鼠或者老鼠逃跑了,对于这两种情况,我们用体重来区分,若猫的 ...
- java面向对象特征及阐述,Java面向对象四个特征
Java面向对象有四个特征:抽象.封装.继承.多态.其中封装.继承.多态又被称为Java的基本特征. 抽象: Java中会把客观事物抽象成一个类.类就是封装了数据以及操作这些数据的代码逻辑实体.用字符 ...
- 20155328 《Java程序设计》 实验二(Java面向对象程序设计) 实验报告
20155328 <Java程序设计> 实验二(Java面向对象程序设计) 实验报告 单元测试 一.单元测试和TDD 编程时需理清思路,将编程需求等想好,再开始编.此部分可用伪代码实现. ...
- 第7篇-JAVA面向对象Ⅲ
第7篇-JAVA面向对象Ⅲ 每篇一句 :任何值得去的地方,都没有捷径 初学心得: 温故而知新 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-04-09| JAVA面向对象 Ⅲ] 1.J ...
- 谈谈java面向对象之抽象,手把手带你搞定java面试之面向对象
计算机语言晦涩难懂,打算利用通俗易懂的文字带领大家学习java基础.如果文中有什么错误的地方,欢迎大家在评论区指正,免得我误人子弟. Question:当面试JAVA开发岗位的时候,面试官最爱问的问题 ...
- java面向对象程序设计第三版_JAVA面向对象程序设计之创建型设计模式
[本文详细介绍了JAVA面向对象程序设计中的创建型设计模式,欢迎读者朋友们阅读.转发和收藏!] 1 基本概念 1.1 什么是设计模式 设计模式( Design pattern )是一套被反复使用.多数 ...
最新文章
- dataframe,python,numpy 问题索引1
- 微信小程序图片上传到服务器再自动替换,微信小程序批量上传图片到服务器,并实现预览,删除功能...
- Linux下nginx+tomcat+memcached集群
- pandas对dataframe的数据行进行随机抽样(Random Sample of Rows):使用sample函数进行数据行随机抽样(有放回的随机抽样,replacement)
- 每一个科学家的内心都住着一位哲学家(节选)
- 算法导论之图的最小生成树
- hibernate 延迟加载(转载)
- 前facebook产品技术leader徐玮:如何建立用户增长机制
- HDU1527 - 取石子游戏【威佐夫博弈】
- java基础篇---网络编程(IP与URL)
- C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)
- Java11.0.2怎么生成JRE_java环境变量配置,jdk13.0.1中没有jre解决办法
- FD.io VPP官方邮件列表
- [渝粤教育] 中国地质大学 大学英语(7) 复习题
- Python_数据类型_字符串的操作
- 为什么需要数据库外键
- 配音鸭 是什么 从哪儿进入 如何使用 手把手指南来了
- 莘城苑:面包种类选择
- winrar去掉烦人的广告 亲测有效
- Spring框架知识
热门文章
- 【蓝桥杯单片机组模块】13、NEC 红外通信 - vs1838B
- Linux的shell脚本教程(一)
- Python代码反向解析列线图nomogram自动计算各项得分及总得分
- 强烈推荐大家看这篇文章:iOS开发常用三方库、插件、知名博客等等(特别有用)
- 人脸识别技术软件测试测什么,人脸识别这么火,你知道它是什么吗?
- 根据经纬度算两点距离
- 微信小程序+vant Weapp Slider 滑块实现滑动拖动计数器
- 坦克采样器加钢琴鼓组弦乐打击音源-IK Multimedia SampleTank 4 v4.1.4 + Library
- COPRA-for-AutoCAD 2005
- sou.php,phpsou RiSearchPHP是一个高效 联合开发网 - pudn.com