一、day06—面向对象1
1、面向对象
所谓的面向对象是一种编程思想,通过这种思想可以把生活中的复杂事情变得简单化,从原来的执行者变成了指挥者,面向对象是基于面向过程而言的。
我们经常说的面向对象的编程实现(OOP,Object Oriented Programming)
三大特征
- 封装性,把相关的数据封装成一个“类”组件
- 继承性,是子类自动共享父类属性和方法,这是类之间的一种关系
- 多态,增强软件的灵活性和重用性
如果说四大特征:就加上抽象
类和对象的关系
类是对象的抽象,对象是类的实例。类是抽象的,不占用内存,而对象的类的实例,是占存储空间的。类就是创建对象的蓝图,好比建筑设计图纸和建筑之间的关系。
--1,测试Phone
package cn.tedu.oop;
//注意:一个.java文件中,可以存在多个类.
//只不过只能有一个类被public修饰,并且这个public的类名就是.java文件的文件名
public class Test2_Class {
public static void main(String[] args) {
//2,通过new关键字,创建对象
// new Phone().call();//匿名对象--一次只干一个活儿
//3,p是引用类型的变量,保存了对象在内存中的地址值
Phone p = new Phone();
System.out.println(p);//cn.tedu.oop.Phone@15db9742
//4,调用模板里的功能
p.call();
p.message();
p.music();
//设置属性的值
p.color = "red" ;
p.size = 5.7 ;
p.pinpai = "HUAWEI" ;
p.price = 5899 ;
//获取属性的值
System.out.println(p.color);
System.out.println(p.size);
System.out.println(p.pinpai);
System.out.println(p.price);
}
}
//1,通过class关键字,创建手机类--抽象的--来描述生活中的手机事物
class Phone{
//特征--成员变量/属性
String color;//颜色
double size; //尺寸
String pinpai;//品牌
int price ;//价格
//行为--成员方法
//修饰符 返回值 方法名(参数列表){方法体}
public void call() {//打电话
System.out.println("call()...");
}
public void message() {//发短信
System.out.println("message()...");
}
public void music() {//听音乐
System.out.println("music()...");
}
}
2、封装
--1,通过private关键,实现封装
是一个权限修饰符,用于修饰成员变量和成员函数,被私有化的成员只能在本类中访问。
想要修改只能,对外提供公共的,get和set方法
--2,为了提高程序的安全性,不让外界随意获取或者修改
//测试 封装
public class Test4_Private {
public static void main(String[] args) {
//创建Student对象测试
Student s = new Student();
//设置属性值
// s.name = "董长虫" ; 被private了,只能在自己类中可见
//6,调用set方法完成间接赋值,把实参拿到以后直接给name属性赋值成功
s.setName("长虫");
s.age = 33 ;
s.gender = '女' ;
//获取属性值
//2,被private了,只能在自己类中可见
// System.out.println( s.name );
//4,访问公共的get(),间接获取name属性的值
// String name = s.getName() ;
// System.out.println(name);
System.out.println( s.getName() );//长虫
System.out.println( s.age );
System.out.println( s.gender );
}
}
//提供Student类
class Student{
//1,通过private关键字,实现封装.只能在本类中可用
private String name ;
//3,提供公共的获取方式--getXxx()--目的是返回属性的值
public String getName(){
return name ;//把name属性的值返回给外界调用位置
}
//5,提供公共的修改方式--setXxx()--目的是设置属性的值
public void setName(String n){
name = n ; //拿到你设置的n的值,给name属性赋值
}
//TODO 封装以下属性,并测试
int age; //0
char gender ;//\u0000
String addr;
double score ;
//行为
public void coding() {
System.out.println("coding()...");
}
public void eat() {
System.out.println("eat()...");
}
}
二、day07—面向对象2
1、构造方法
--1,概述
--创建对象时会自动调用构造方法
--构造方法和其他方法一样也可以重载
--作用:完成对象的创建或者完成对象的初始化
--2,语法:
--普通方法:修饰词 返回值 方法名(参数列表){方法体}
--构造方法:修饰符 类名(参数列表){方法体}
–3,构造方法完成创建对象
//测试 构造方法Constructor / 构造器
//总结
//1,触发的时间节点:构造方法摆在那儿不会主动执行,需要new来触发
//2,构造方法可以重载,为了方便各种new,体现程序的灵活性
//3,构造方法在创建对象时,会自动执行
public class Test1_Constructor {
public static void main(String[] args) {
//创建对象测试
new Student("1",2);//触发了public Student(String a,int b)
new Student();//触发无参构造
new Student("1");//触发了public Student(String name)
new Student(1);//触发了public Student(int a)
new Student(1,2);//触发了public Student(int a,int b)
}
}
//创建Student类
class Student{
public Student(String a,int b) {
System.out.println("含参构造,名字是:"+a+",年龄是:"+b);
}
//1,提供构造方法:修饰符 类名(参数列表){方法体}
//5,默认就会存在无参构造--前提是.不能只提供含参的构造方法
public Student() { }
//3,重载-- 在同一个类里,方法名相同,但是参数列表不同
public Student(String name) {
System.out.println("含参构造方法"+name);
}
public Student(int a) {
System.out.println("含参构造方法"+a);
}
public Student(int a,int b) {
System.out.println("含参构造方法"+a+b);
}
}
2、代码块
--1,概述
--被花括号包起来的一段代码就叫代码块
--代码块的位置不同,作用用法名字都不同
--2,构造代码块
--成员位置(类里方法外)的代码块叫构造代码块
--作用:通常用于抽取构造方法中的共性代码
--顺序:new时,先调用构造代码块,然后调用构造方法,优先于构造方法加载
--3,局部代码块
--局部位置(方法里)的代码块叫局部代码块
--作用:通常用于控制变量的作用范围
/测试 代码块
//总结
//1,创建对象时:本来是只会触发构造方法,但是,如果有构造代码块,就会先触发构造代码块再执行构造方法
//2,调用方法时:顺序执行方法里的代码,如果有局部代码块也就一起执行
//3,执行顺序:new时--构造代码块>构造方法,调用方法时--局部代码块
//4,构造代码块--用来提取构造方法的共性--new时才触发
//5,局部代码块--用来控制变量的作用范围--调用方法时才触发
public class Test3_Block {
public static void main(String[] args) {
new Person().show();//触发无参构造
new Person("熊大");//触发含参构造
}
}
//创建Person类
class Person{
//1,构造代码块:位置是在成员位置--触发节点是 new时--先执行构造代码块再执行构造方法
//--作用:抽取构造方法的共性
int age ;
{
age = 0 ;//提取了所有构造方法的共性功能
System.out.println("构造代码块");
}
public Person() {
System.out.println("无参构造方法"+age);
}
public Person(String name) {
System.out.println("含参构造方法"+name+age);
}
//2,局部代码块:位置是在方法里--触发节点是 当方法被调用时--用来控制变量的作用范围
public void show() {
{
int x = 10;
System.out.println(x);
System.out.println("局部代码块");
}
}
}
3、this关键字
--1,代表本类对象的一个引用对象
--2,作用:
--用来区分同名的成员变量和局部变量
--用来完成构造方法间互相调用
//测试 this关键字
//总结
//当局部变量名 和 成员变量名 相同时,需要用this调用 成员变量
public class Test4_This {
public static void main(String[] args) {
//通过对象,来访问类里的成员(成员变量和成员方法)
new Demo().test();
// Demo d = new Demo() ;
// System.out.println( d.name );
System.out.println( new Demo().name );
}
}
//创建Demo类
class Demo{
String name ;
int count = 20 ;//成员变量
public void test() {
int count = 10;//局部变量
System.out.println(count);//变量的就近原则,会使用局部变量 的值 10
System.out.println(name);//成员变量
//1,想要使用 和 局部变量 同名的 成员变量count--this调用成员变量
//this表示的是本类的对象的引用--底层帮你new了一个本类对象--Demo this = new Demo();
System.out.println( this.count );//20,成员变量
}
}
//测试 this--用来完成 构造方法间 互相调用
//总结
//1,如果在构造方法间,互相调用时,this不能省略
//2,位置必须是第一条语句
public class Test5_This2 {
public static void main(String[] args) {
// new Demo2();
new Demo2(1);
}
}
class Demo2{
public Demo2() {
//1,在 无参构造里 调用 含参构造
// this(10);
System.out.println("无参构造");
}
public Demo2(int a) {
//2,在 含参构造里 调用 无参构造
this();//3,在构造方法中,使用this关键字,必须是第一条语句
System.out.println("含参构造"+a);
}
}
4、继承
--1,概述
Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数 据或新 的功能,也可以用父类的功 能,但不能选择性地继承父类/超类/基类。
--2,好处
提高父类代码的复用性,减少子类代码的编写,提高开发效率
--3,特点
--使用extends关键字
--相当于子类把父类的功能复制了一份
--java只支持单继承
--继承可以传递(爷爷,儿子,孙子的关系)
--不能继承父类的私有成员
--继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展
--像是is a 的关系
4、测试继承
//测试 继承
public class Test6_Extends {
public static void main(String[] args) {
//创建Dog对象测试
new Dog().eat();
new Dog().sleep();
System.out.println( new Dog().name );
}
}
class God{
String name ;
}
//1,父类来了--提取子类的共性--提高了代码的复用性
class Animal extends God{
//5,父类的私有成员(成员变量/成员方法)不能被继承
private double sifangmoney = 100 ;
public void eat() {
System.out.println("啥都吃");
}
}
//2,子类想拥有父类的功能--需要发生继承关系
class Dog extends Animal{//4,java只支持单继承
//3,相当于子类把父类的功能复制了一份
//6,除了能用父类继承来的,还可以自己做扩展java
public void sleep() {
System.out.println("sleep()..");
}
}
class Cat{
}
–5,super关键字
–1,在子类中用,用来访问父类的成员(成员变量/成员方法)
–2,super表示父类对象的引用,底层自动创建了一个父类的对象
–3,如果在构造方法里使用super关键字,位置上必须是第一条语句
–6,方法的重写override
–1,重写的前提是:发生继承关系+子类的方法声明和父类一样
–2,啥时候需要重写?–想要改,改掉父类原来的实现时
5、this和super的区别
1、 this代表本类对象的引用,super代表父类对象的引用。
2、 this用于区分局部变量和成员变量
3、 super用于区分本类变量和父类变量
4、 this.成员变量 this.成员方法() this(【参数】)代表调用本类内容
5、 super.成员变量 super.成员方法() super(【参数】),代表调用父类内容
6、 this和super不可以同时出现在同一个构造方法里,他们两个只要出现都得放在第一行,同时出现的话,到底第一行放谁呢。
6、 重载与重写的区别(Overload和Override的区别)
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分
三、day08—面向对象3
1、static关键字
–1,特点
–可以修饰成员变量,成员方法
–可以直接被类名调用
–随着类的加载而加载,优先于对象加载
–只加载一次,就会一直存在,不再开辟新空间
–全局唯一,全局共享
–static不能和this或者super共用,因为有static时可能还没有对象
–静态只能调用静态,非静态可以随意调用
测试:
//测试 静态关键字
//总结:
//1,静态的调用关系---静态只能调用静态--非静态调用啥资源都可以
//2,静态资源是加载非常早的,随着类的加载就已经加载进内存了,比对象早
//3,静态资源的访问方式:通过对象调用 + 通过类名调用
public class Test4_Static {
public static void main(String[] args) {
//2,静态资源优先于对象加载,因为是随着类的加载就已经加载了
Student.coding();
System.out.println(Student.name);
Student s = new Student();
s.study();
System.out.println(s.age);
//1,静态资源,多了一种访问方式,除了可以用对象访问,更提倡用类名直接调用
// s.coding();
// System.out.println(s.name);
Student.coding();
System.out.println(Student.name);
//3,静态资源是共享资源,能够被多个对象共享
Student s1 = new Student();
s1.name="陈子枢";
Student s2 = new Student();
System.out.println(s2.name);//陈子枢
}
}
class Student{
//普通资源
int age = 10;
public void study() {
//6,非静态调用关系? -- 调用任意资源
System.out.println(age);
System.out.println(name);
coding();
System.out.println("正在学习java");
}
//静态资源
static String name ;
static public void coding() {
//4,静态资源里,不能使用this或者super关键字!
// this.study();
// super.
//5,静态调用关系? -- 只能调用静态,不能调用非静态的
System.out.println(name);
// study();
System.out.println("正在敲代码");
}
}
static修饰的方法不能被重写可以被继承
public class StaticLearnig {
public static void main(String[] args) {
SuperClass superClass=new SubClass();
superClass.a();
superClass.b();
}
}
/*
结果:
SuperClass a
SubClass b
*/
class SuperClass{
//静态方法
public static void a(){
System.out.println("SuperClass a");
}
//非静态方法
public void b(){
System.out.println("SuperClass b");
}
}
class SubClass extends SuperClass{
//静态方法
public static void a(){
System.out.println("SubClass a");
}
//非静态方法
public void b(){
System.out.println("SubClass b");
}
}
静态的方法可以被继承,但是不能重写。如果父类中有一个静态的方法,子类也有一个与其方法名,参数类型,参数个数都一样的方法,并且也有static关键字修饰,那么该子类的方法会把原来继承过来的父类的方法隐藏,而不是重写。通俗的讲就是父类的方法和子类的方法是两个没有关系的方法,具体调用哪一个方法是看是哪个对象的引用;这种父子类方法不在存在多态的性质。
静态方法内存图:
2、static代码块
1、 静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化
2、 构造代码块:在调用构造方法前会自动调用,每次创建对象都会被调用
3、 局部代码块:方法里的代码块,方法被调用时才会执行
4、 静态代码块:static{ },位置:在类里方法外
5、 TODO创建测试类,类中写好静态代码块,构造代码块,构造方法,普通方法里嵌套局部代码块。测试他们的执行顺序。
6、 静态 - 构造代码块 - 构造方法 - 局部
//测试 代码块
//1,静态代码块:用来初始化项目--位置在成员位置
//2,执行顺序:
//类加载时 : 静态代码块
//实例化时 : 构造代码块 > 构造方法
//方法调用时 : 局部代码块
public class Test5_Block {
public static void main(String[] args) {
StaticDemo s = new StaticDemo();//先执行构造代码块然后执行构造方法
s.show();//执行局部代码块
StaticDemo s2 = new StaticDemo();
}
}
class StaticDemo{
//静态代码块--位置也是在成员位置--用来完成项目的初始化
//--只加载一次,在类第一次被加载时就跟着一起加载了(类的资源)
static{
System.out.println("静态代码块");
}
//构造代码块--位置是在成员位置--用来提取构造方法的共性
{
System.out.println("构造代码块");
}
//构造方法
public StaticDemo() {
System.out.println("构造方法");
}
//局部代码块--位置是在方法里--用来控制变量的作用范围
public void show() {
{
System.out.println("局部代码块");
}
}
}
3、final关键字
1、 被final修饰的类,不能被继承
2、 被final修饰的方法,不能被重写
3、 被final修饰的变量是个常量,值不能被更改
4、 常量的定义形式: final 数据类型 常量名 = 值
让子类的重写权限变得可控.如果父类的某个方法不让子类重写,可以用final修饰变成最终方法
//测试 final关键字
//1,final 修饰的类是最终的类,不能被继承
//2,final 修饰的变量,是一个最终的变量,值不能被修改,称之为是常量
//3,final 修饰的方法,不能被重写
public class Test6_Final {
public static void main(String[] args) {
//创建子类对象测试
Son s = new Son();
s.eat();
// s.sum = 20 ;//final前可以改也能使用
System.out.println(s.SUM);
}
}
//1,final修饰的类是最终的类,不能被继承--The type Son cannot subclass the final class Father
//final class Father{
class Father {
//3,final 修饰的变量,final用来修饰常量--The final field Father.sum cannot be assigned
// final int sum = 10 ;
static final int SUM = 10 ;
//2,final 修饰的方法,只能用不能被重写--Cannot override the final method from Father
final public void eat() {
System.out.println("Father...eat()");
}
}
class Son extends Father{
// //想要改,发生了重写!!
// public void eat() {
// System.out.println("Son...eat()");
// }
}
4、多态
1,就是指同一个对象,在不同时刻,代表的对象不同.就是指同一个对象的多种形态.
2,多态的作用 – 用来统一调用标准!!! 一切向父类看齐
3,好处是 : 做出通用编程,本质上就是不关心具体的子类的类型,屏蔽了子类之间的不同,可以把子类当做父类来看.
4,特点
–前提: 继承关系 + 方法的重
//测试 多态
public class Test7_Multi {
public static void main(String[] args) {
//创建子类对象测试
new Dog().eat();//重写前执行父类的,重写后执行子类的
//创建多态对象测试
Animal a = new Dog();//口诀1:父类引用 指向 子类对象
//口诀2:编译看左边,运行看右边
//编译看左边--是指想要保存成功,向左边也就是 向父类看齐--统一标准!!
//运行看右边--是指结果向右边看齐也就是看子类的干活结果
a.eat();//狗吃肉
// a.test();//test()是子类的特有方法,多态对象只能调用 父类的
}
}
class Animal{
public void eat() {
System.out.println("啥都吃");
}
}
//1,多态的前提:继承 + 方法重写(方法声明和父类一样)
class Dog extends Animal{
public void eat() {
System.out.println("狗吃肉");
}
public void test() {
System.out.println("test...");
}
}
5、多态的使用
–1,成员变量
–2,成员方法
–3,静态成员
–4,测试
//测试 多态的使用
//总结
//1,多态中,的成员变量 -- 用父类的
//2,多态中,的成员方法 -- 用父类的方法声明,用子类的方法体
//TODO 3,多态中 ,的 静态资源?
public class Test8_UseMulti {
public static void main(String[] args) {
//创建多态对象--父类引用 指向 子类对象
Fu4 fu = new Zi4();
//编译看左边,运行看右边
System.out.println( fu.name );//成员变量用谁的?--父类的
//多态中,方法声明用--父类的 ,方法体用--子类的(因为重写了)
fu.show();//成员方法用谁的?--子类的(重写了)
fu.test();//成员方法用谁的?--父类的(没重写)
}
}
class Fu4{
String name = "尼古拉斯.赵四" ;
public void show() {
System.out.println("Fu4...show()");
}
final public void test() {//被final了,不让子类重写了!
System.out.println("Fu4...test()");
}
}
class Zi4 extends Fu4{
String name = "Anglelababa";
public void show() {
System.out.println("Zi4...show()");
}
}
6、向上转型和向下转型
在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。
在应用中就存在着两种转型方式,分别是:向上转型和向下转型。
比如:父类Parent,子类Child
向上转型:父类的引用指向子类对象Parent p=new Child();
说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类的方法就根据这个引用指向调用子类重写方法。
向下转型(较少):子类的引用的指向子类对象,过程中必须要采取到强制转型。
Parent p = new Child();//向上转型,此时,p是Parent类型
Child c = (Child)p;//此时,把Parent类型的p转成小类型Child
//其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的
说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。
四、day09—面向对象4
1、异常
- 异常继承结构:
- 异常处理
–当一段代码出现异常时,可以有两种解决方案:捕获和抛出
–捕获:自己处理异常,别人调用就没有后患–推荐
–语法:把有问题的代码包起来
try{
代码
代码
代码
}catch(异常类型1 异常名){
合理的解决方案1
}catch(异常类型2 异常名){
合理的解决方案2
}catch(异常类型3 异常名){
合理的解决方案3
}
–抛出:自己不处理,交给调用者处理
–语法:
在方法声明上加 throws 异常类型
例:main() throws InputMismatchException
- 测试
import java.util.InputMismatchException;
import java.util.Scanner;
//测试 异常
public class Test1_Exception {
public static void main(String[] args){
// method();//暴露异常
// method2();//捕获异常
try {
//调用了抛出异常的method3(),需要处理,捕获或者抛出二选一
method3();//抛出异常
}catch(Exception e) {
System.out.println("运算错误!");
}
}
/* 抛出异常
* 在方法声明上加 throws 异常类型1,异常类型2...
*/
public static void method3()
// throws ArithmeticException,InputMismatchException{
//多态,Exception体现了程序的通用性,可以把所有异常抛出去
throws Exception{
int a = new Scanner(System.in).nextInt();
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}
/* 捕获异常
* try{ 代码... }catch(异常类型 异常名){ 合理的解决方案 }
* 异常类型: ArithmeticException / InputMismatchException
*/
public static void method2() {
try {
int a = new Scanner(System.in).nextInt();
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}catch(InputMismatchException a) {
System.out.println("请输入两次整数!");
}catch(ArithmeticException a) {
System.out.println("第二次输入的整数不能为0 !");
}catch(Exception a) {
//怎么捕获其他的所有异常呢?--多态--通用性强-不关心子类类型,把子类当做父类来看
//所有Exception的子类都能被捕获!
System.out.println("请输入正确的数据!!");
}
}
//暴露异常
public static void method() {
//1,接收键盘输入的两个整数
int a = new Scanner(System.in).nextInt();
int b = new Scanner(System.in).nextInt();
//2,做除法运算
System.out.println(a/b);
}
}
2、访问控制符
类的访问权限:
public:公共的,能被同个项目中的所有类访问(“必须和文件名相同”)
default:默认的,可被同个包中的类访问。
成员(成员变量或者成员方法)的访问权限
public:公共的,能被同个项目中的所有类访问。
protected:受保护的,能够被自己本身访问,能够被同个包中的所有类访问,能够 被自己的子类(不在同个包也可以)访问。
default:默认的,能够被自己访问,能够被自己同个包中的其他类访问。
private:私有的,能够被自己访问。
//测试 方法重写
//四种修饰符,关系:public > protected > default > private
public class Test2_Override {
public static void main(String[] args) {
}
}
class Animal{
void eat() {//是默认修饰符 default
System.out.println("啥都吃");
}
}
class Dog extends Animal{
//方法重写时,要求子类的方法声明(返回值 方法名(参数列表))和父类一样
//1,要求方法重写时,要有足够的权限.子类的重写权限>=原有权限
public void eat() {
System.out.println("只吃肉");
}
}
3、抽象类
–1,概述
Java中可以定义没有方法体的方法,该方法由其子类来具体的实现。该没有方法体的方法我们称之为抽 象方法,含有抽象方法的类我们称之为抽象类。
–2,特点
–通过java关键字abstract实现
–可以修饰方法或者类
–抽象类中可以没有抽象方法(由子类去实现)
–如果类中有抽象方法,那该类必须定义为一个抽象类
–子类继承了抽象类以后,要么还是一个抽象类,要么就把所有抽象方法都重写
–多用于多态中
–抽象类不可以被实例化
3,测试:
import java.io.IOException;
import java.io.Reader;
//测试 抽象类
public class Test3_Abstract {
public static void main(String[] args) {
//创建多态对象--父类引用 指向 子类对象
// Animal2 a = new Dog2();//8,抽象类不能被实例化
Animal2 a = new Cat2();
a.eat();//父类的方法声明,父类的方法体
a.sleep();//父类的方法声明,子类的方法体(重写了)
}
}
//1,为什么产生父类?--为了提取子类的共性,提高父类代码的复用性
//2,怎么优化父类?--程序设计--父类有没有可以省略的功能--方法体可以省略
//4,如果类里包含抽象方法,那么,这个类就是一个抽象类
//5,使用abstract关键字描述抽象
abstract class Animal2{
public void eat() {
System.out.println("Animal...eat()");
}
//3,如果方法体,写了也要被修改,那就可以省略不提供--没有方法体的方法--抽象方法
abstract public void sleep() ;
}
//6,子类继承抽象类后,就继承来了抽象方法,是一个 抽象的 子类
abstract class Dog2 extends Animal2 {
}
//7,子类继承抽象类后,子类可以重写 所有的 抽象方法
class Cat2 extends Animal2 {
// abstract public void sleep() ;
@Override//注解,作用是用来标志这个方法是一个重写方法
public void sleep() {
System.out.println("猫吃鱼");
}
}
//要么重写 所有的 抽象方法,要么就是一个抽象类
//abstract class SubReader extends Reader{
class SubReader extends Reader{
//抽象方法必须重写,否则就是一个抽象类
//普通方法不是必须重写,而是要改才重写
// abstract public void close() throws IOException;
public void close() throws IOException{
System.out.println("close() ");
}
// abstract public int read(char cbuf[], int off, int len) throws IOException;
public int read(char cbuf[], int off, int len) throws IOException{
System.out.println("read() ");
return 0 ;
}
}
4、使用抽象类
--构造方法
//测试 抽象类的 构造方法
//总结
//1,抽象类 里 有构造方法
//2,抽象类自己不能被实例化,仍然会提供构造方法,因为方便子类new
//3,当创建子类对象时,会触发子类的构造方法,子类的构造方法里第一条默认就会有super()
//4,构造方法的执行顺序: 父类的 > 子类的
public class Test4_Abstract2 {
public static void main(String[] args) {
//2,先执行父类的 构造方法 ,再执行自己的构造方法
Animal3 a = new Dog3();
}
}
//创建抽象类
abstract class Animal3{
//3,抽象类不能被实例化,为什么还要提供构造方法?--为了方便子类new
public Animal3() {
System.out.println("Animal3..无参构造");
}
}
class Dog3 extends Animal3{
public Dog3() {
super();//1,默认就存在,会主动找父类的无参构造
System.out.println("Dog3..无参构造");
}
}
--成员变量
//测试 抽象类的 成员变量
//总结
//1,抽象类里可以有变量 也可以有常量
//2,常量的值不能被修改,final的资源可以被继承但是不能被修改
public class Test5_Abstract3 {
public static void main(String[] args) {
System.out.println( new Demo2().age );
// new Demo2().name = "123" ;final的常量,值不能被修改
System.out.println( new Demo2().name );
}
}
abstract class Demo{
int age = 10 ;
final String name = "Demo";
}
class Demo2 extends Demo{
}
--成员方法
//测试 抽象类的 成员方法
//总结
//1,抽象类里可以都是抽象方法,要求子类重写 所有的 抽象方法,否则就是一个抽象的子类
//2,抽象类里可以都是普通方法,目的是不让外界实例化
//3,抽象类里包含抽象方法和普通方法,要求子类,重写 所有的 抽象方法,否则就是一个抽象的子类
//4,抽象类是一个特殊的类,特殊在 抽象类里可以有抽象方法
//5,抽象类的方法到底设计成普通方法还是抽象方法呢? -- 看方法体
public class Test6_Abstract4 {
public static void main(String[] args) {
Demo3 d = new Demo5();//Demo3 Demo4都是抽象类不能new
d.save();//多态的目的是统一标准,一切向父类看齐
d.delete(10);
d.update("jack");
}
}
//1,抽象类是一个特殊的类,特殊在 类里可以有普通方法和 抽象方法
//怎么决定类里的方法到底设计成普通方法还是抽象方法呢?--看方法体有没有必要提供
abstract class Demo3{
public void save() {
System.out.println("数据保存成功!");
}
abstract public void delete(int id) ;
abstract public void update(String name) ;
}
//2,子类继承了抽象类,只重写了一部分抽象方法,
//也就是还包含着抽象方法,所以仍然是一个抽象类
abstract class Demo4 extends Demo3{
// abstract public void delete(int id) ;
public void delete(int id) {
System.out.println("delete().."+id);
}
}
class Demo5 extends Demo4{
// abstract public void update(String name) ;
public void update(String name) {
System.out.println("update().."+name);
}
}
五、day10—面向对象5
1、接口
–1,概述
–接口的产生,是为了突破java单继承的局限性
–提倡面向接口,面向抽象编程
–是指把抽象层,修饰成接口或者抽象类
–2,特点
–接口中都是抽象方法
–通过interface关键字创建接口
–通过implements让子类来实现
–可以理解成,接口是一个特殊的抽象类
–接口突破了java的单继承的局限性
–接口和类之间可以多实现,接口和接口之间可以多继承
–接口是对外暴露的规则,是一套开发规范
–接口提高了程序的功能扩展,降低了耦合性
3,入门案例:
//测试 接口
public class Test1_Inter {
public static void main(String[] args) {
//6,接口和抽象类一样,都不可以被实例化
// new Demo();
Demo d = new DemoImpl();
//7,多态对象为了统一调用标准,以父类为准
d.save();
d.delete();
}
}
//1,通过interface关键字,定义接口
interface Demo{
//2,接口里全都是抽象方法(jdk1.8后可以是default/static的普通方法)
abstract public void save() ;
abstract public void delete() ;
}
//3,实现类想要使用接口的功能,需要和接口发生实现关系(类似继承)
//5,实现类实现了接口,可以重写 所有 抽象方法
class DemoImpl implements Demo{
// abstract public void save() ;
@Override//注解
public void save() {
System.out.println("数据保存成功!");
}
// abstract public void delete() ;
@Override//注解
public void delete() {
System.out.println("数据删除成功!");
}
}
//4,实现类实现了接口,可以是一个抽象的实现类
//abstract class DemoImpl implements Demo{}
2、接口的用法
–1,构造方法
–2,成员变量
–3,成员方法
//测试 接口的使用
//总结
//1,接口里的构造方法--没有!!
//2,接口里的变量--没有!有静态的常量,为变量自动拼接public static final
//3,接口里的方法--都是抽象方法(1.8前),也可以有static或者default的普通方法(1.8后)
//4,实现类--重写所有 抽象方法,否则就是一个抽象的 实现类
//问题--接口里没有构造方法,那么,实现类怎么new的?
//答案--不是接口里的构造方法,因为接口根本没有构造方法,其实找的是Object的构造方法
public class Test2_Inter {
public static void main(String[] args) {
//3,使用接口里的静态常量?
// Inter.age = 30 ;//是final的常量
System.out.println( Inter.age );//是static的资源
System.out.println( new InterImpl().age );
//8,测试
Inter in = new InterImpl();
in.show();
in.save();
Inter.test();//通过类名直接访问接口里的普通的静态方法
}
}
interface Inter{
//1,接口里有没有构造方法?--没有--实现类到底怎么new的?--
// public Inter() {
// System.out.println(123);
// }
//2,接口里有没有变量?--没有!!是static的final的常量public的
// public static final int age = 20 ;//接口会为你的变量,自动拼接public static final
int age = 20 ;//简写形式
//4,接口里有没有普通方法?--有,只不过是jdk1.8才提供的,必须修饰成default/static
default public void show() {
System.out.println("这是jdk1.8的新特性");
}
static public void test() {
System.out.println("这是jdk1.8的新特性");
}
//5,接口里有没有抽象方法?--有
abstract public void save() ;
//abstract public void save() ;//接口会为你的抽象方法,自动拼接public abstract
void save() ;//简写形式
}
//6,实现类实现接口后,对于普通方法必须重写吗?--不是,要改才重写
//7,实现类实现接口后,对于抽象方法必须重写吗?--是,否则就是一个抽象的实现类
class InterImpl extends Object implements Inter{
public InterImpl() {
//不是接口里的构造方法,因为接口根本没有构造方法,其实找的是Object的构造方法
super();
}
@Override
public void save() {
System.out.println("数据保存成功!");
}
}
3、接口的复杂用法
import java.io.Reader;
//测试 接口的复杂用法
//总结
//1,继承关系extends: 子类和父类 / 接口和接口
//2,实现关系implements: 实现类 和 接口
//3,定义类: class / abstract class
//4,定义接口: interface
//5,子类继承了父类后,如果有抽象方法,需要重写,否则就是一个抽象的子类
//6,实现类 实现了 接口后,需要重写接口里的 所有抽象方法,否则就是一个抽象的实现类
public class Test3_Inter {
public static void main(String[] args) {
//2,左侧写的接口到底是谁?--要看你想用哪个接口的功能,左侧就写谁
Inter2 in = new Inter2Impl() ;
in.save();
int rows = in.update(2) ;
System.out.println(rows);
System.out.println( in.update(2) );
in.delete("jack");
}
}
interface Inter1{
void save();
int update(int id);
}
interface Inter3{
void delete(String name);
}
//1,接口间是继承关系,而且可以多继承
interface Inter2 extends Inter1 , Inter3{
}
//4,实现类和接口,是实现关系,还可以多实现
class Inter3Impl implements Inter3 , Inter1 {
public void delete(String name) {
System.out.println("删除成功!");
}
public void save() {
System.out.println("保存成功!");
}
public int update(int id) {
System.out.println("更新成功!");
return 5;
}
}
//5,实现类可以在单根继承的同时,多实现
//Inter4Impl需要重写Inter1和Inter3里的 所有抽象方法,否则就是一个抽象类
abstract class Inter4Impl extends Object implements Inter1 , Inter3{
//Inter4Impl需要重写Inter1和Inter3和抽象类Reader里的 所有抽象方法,否则就是一个抽象类
//abstract class Inter4Impl extends Reader implements Inter1 , Inter3{
}
//3,实现类,实现了接口.需要把接口里 所有抽象方法都重写.
//Inter2接口里的3个方法都要重写
class Inter2Impl implements Inter2{
@Override
public void delete(String name) {
System.out.println("删除记录成功!"+name);
}
@Override
public void save() {
System.out.println("数据保存成功!");
}
@Override
public int update(int id) {
System.out.println("数据已经更新");
return 5;
}
}
六、总结
1、类和类的关系:继承 extends / 单继承 / 单根继承
-- 继承的意义:为了提高代码的复用性,减少了代码的编写提高开发效率。
-- 方法重写的意义:在不修改父类源码的前提下,在子类中重写业务,从此使用的就是重写后的功能。
-- 要求子类的方法声明和父类一样,只要改方法体。
-- 有了继承有了重写就产生了多态,多态的意义:为了统一程序的调用标准,标准就是父类。
-- 多态 也就是向上转型/向上造型。
-- 向下造型的意义:很少用,相当于想要使用子类的特殊功能,还不如直接创建子类对象简单。
-- class A extends B
-- 其中,A和B都是类,A是子类,B是父类,A就拥有了B的所有功能(除了私有的和构造方法)
-- 其他知识点:this 和super ,构造方法,各种代码块...
2、类和接口关系:实现implements / 单实现 / 多实现
-- class A implements B,C
-- 其中,A是实现类,B和C是接口
-- 要求A 可以把 B 和C 接口里的所有 抽象方法 都重写掉,否则 A 就是抽象类
-- 接口不能创建对象
-- 接口里没有构造方法,接口里都是常量,接口里都是抽象方法
3、接口和接口关系:继承extends / 单继承 / 多继承
-- 接口的多继承的关系,打破了java单继承的局限性
-- interface A extends B,C
-- 其中,A B C 都是接口,A是子接口,同时拥有B和C接口里的所有功能
-- class AImpl implements A
-- 要求AImpl需要重写A接口里的所有方法(是包含B和C接口的所有方法),否则就是抽象类
4、接口和抽象类的区别!!!
-- 相同点:都是抽象层,都不能实例化
-- 不同点:
-- 1、抽象类用abstract关键字描述,接口用interface
-- 2、子类和抽象类之间是extends关系,实现类和接口之间是implements关系
-- 3、抽象类中 可以 有构造方法 ,接口里 不能 出现 构造方法
-- 4、抽象类里可以有 变量,接口里没有变量全都是静态的常量
-- 5、接口里定义常量的语法:public static final String NAME="jack",会为变量自动拼接public static final
-- 6、抽象类里 可以有普通方法 也可以有 抽象方法,接口都是抽象方法
-- 7、抽象类和子类之间是继承关系,而且java中,只支持单继承
-- 8、接口突破了java单继承的局限性,因为接口可以多继承也可以多实现,甚至可以继承的同时多实现
-- 9、接口的复杂用法
-- 多继承: interface A extends B,C 其中A是子接口,同时拥有自己的和BC的功能
-- 多实现: class AImpl implements M,N,O,P 其中AImpl是实现类,需要同时重写MNOP的所有抽象方法,否则就是一个抽象类
.
2、类和接口关系:实现implements / 单实现 / 多实现
-- class A implements B,C
-- 其中,A是实现类,B和C是接口
-- 要求A 可以把 B 和C 接口里的所有 抽象方法 都重写掉,否则 A 就是抽象类
-- 接口不能创建对象
-- 接口里没有构造方法,接口里都是常量,接口里都是抽象方法
3、接口和接口关系:继承extends / 单继承 / 多继承
-- 接口的多继承的关系,打破了java单继承的局限性
-- interface A extends B,C
-- 其中,A B C 都是接口,A是子接口,同时拥有B和C接口里的所有功能
-- class AImpl implements A
-- 要求AImpl需要重写A接口里的所有方法(是包含B和C接口的所有方法),否则就是抽象类
4、接口和抽象类的区别!!!
-- 相同点:都是抽象层,都不能实例化
-- 不同点:
-- 1、抽象类用abstract关键字描述,接口用interface
-- 2、子类和抽象类之间是extends关系,实现类和接口之间是implements关系
-- 3、抽象类中 可以 有构造方法 ,接口里 不能 出现 构造方法
-- 4、抽象类里可以有 变量,接口里没有变量全都是静态的常量
-- 5、接口里定义常量的语法:public static final String NAME="jack",会为变量自动拼接public static final
-- 6、抽象类里 可以有普通方法 也可以有 抽象方法,接口都是抽象方法
-- 7、抽象类和子类之间是继承关系,而且java中,只支持单继承
-- 8、接口突破了java单继承的局限性,因为接口可以多继承也可以多实现,甚至可以继承的同时多实现
-- 9、接口的复杂用法
-- 多继承: interface A extends B,C 其中A是子接口,同时拥有自己的和BC的功能
-- 多实现: class AImpl implements M,N,O,P 其中AImpl是实现类,需要同时重写MNOP的所有抽象方法,否则就是一个抽象类
-- 继承的同时多实现: class AImpl extends Object implements M,N 一定是先继承后实现