目录面向对象基础入门一、包1.1 语法格式1.2 类在不同包的访问权限1.3 配置自动导包1.4 如何使用不同包下的同名类二、权限修饰符2.1 概念2.2 作用范围2.3 代码案例三、final关键字3.1 final修饰类3.2 final修饰方法3.3 final修饰变量3.4 final修饰引用类型3.5 final小结四、常量和枚举4.1 什么是常量4.2 常量的编译优化4.3 常量做信息标志和分类4.4 枚举的格式4.5 反编译查看枚举的特点4.6 枚举的作用:入参约束五、抽象类和抽象方法5.1 基本介绍5.2 基本使用5.3 案列--加油卡5.4 抽象类的特征和注意事项5.5 为什么抽象类(不管里面有没有抽象方法)都不能实例化?5.6 abstract和final的关系5.7 总结六、接口6.1 什么是接口6.2 接口对类的规范约束:被类实现(多实现)6.3 接口多继承的作用:规范合并6.4 JDK8开始:接口新增方法介绍默认方法静态方法私有方法6.5 使用接口的注意事项七、多态7.1 基本介绍7.2 向上转型(自动类型转换)7.3 多态的优缺点解耦合易拓展不能调用子类独有方法(向下转型可以解决此问题)7.4 向下转型(强制类型转换)7.5 综合案列:设计一个电脑对象八、内部类8.1 内部类的使用场景8.2 静态内部类(了解)8.3 成员/实例内部类(了解)8.4 局部内部类(了解)8.5 匿名内部类(重点掌握)基本介绍代码案例匿名内部类的.class文件匿名内部类常见使用形式匿名内部类真实案例与简化代码总结九、Lambda表达式9.1 函数式接口9.2 基本使用9.3 简化的案例9.4 省略规则(进一步简化)9.5 总结面向对象基础入门Java基础复习03:面向对象基础入门(类与对象的概念 构造器 this 封装 static 继承 super)一、包1.1 语法格式先建包 再建类 IDEA会自动写好建包语句1.2 类在不同包的访问权限相同包下的类可以直接访问不同包下的类必须先导包(import 包名.类名) 才可以使用1.3 配置自动导包快捷键Alt回车就可以导包也可以配置一下光标移动到报错的类名上就可以提示导包:1.4 如何使用不同包下的同名类如果一个类中需要用到两个不同类 但是这两个类的名称是一样的那么只能默认导入一个类 另一类访问要带上包名二、权限修饰符2.1 概念修饰成员变量 方法 构造器 内部类2.2 作用范围同类访问权限private:只有本类能访问包访问权限缺省:同一个包下才能访问子类访问权限protected:同一个包下可以访问不同包下的子类能访问public:全都ok2.3 代码案例针对Fu类下的四个成员方法1.在Fu本类中2.不在Fu本类 但是和Fu在同一个包下的Test类3.不和Fu类在同一个包下 但是是Fu类的子类Zi类4.不和Fu类在同一个包下 也不是Fu类的子类 只能访问到public三、final关键字3.1 final修饰类被修饰的类是最终类 无法再被继承工具类 就可以用final修饰(因为直接工具类.使用就行了 不需要继承)3.2 final修饰方法被修饰的方法是最终方法不能再被重写模版方法是给子类去直接用的 不要重写 可以用final修饰3.3 final修饰变量Java中变量的分类final修饰局部变量不能被第二次赋值final修饰静态成员变量这个schoolName其实也是个常量final修饰实例成员变量(很少用实例跟对象在一起 而对象一般都不是固定值)就跟在{实例代码块}里给name赋值一样 也不合理3.4 final修饰引用类型指向的对象不能变但是对象里的东西可以发生变化3.5 final小结四、常量和枚举4.1 什么是常量public static final修饰 必须初始化关键是static final不一定是public4.2 常量的编译优化编译阶段完成替换4.3 常量做信息标志和分类硬编码可读性不好:常量就很适合做信息标注:一般还会把常量都定义在常量包统一管理4.4 枚举的格式枚举是一种特殊的类 他是一个固定了对象数量的类4.5 反编译查看枚举的特点1.枚举类都继承了java.lang.Enum2.枚举都是最终类final修饰 不可以被继承3.枚举类的构造器都是私有的所以枚举类对外不能new出新对象(枚举类对应它固定的那几个对象 所以也是多例模式)4.枚举类都第一行默认都是枚举类具体对象的名称(用常量存的对象)所以枚举也可以实现单例模式(构造器是私有的 只有X这一个对象) 而且线程安全4.6 枚举的作用:入参约束常量的问题所在没有参数的合理约束枚举可以增加可读性(信息分类) 并且有入参约束(传参只能是枚举类那几个对象 不能瞎传参数)可以看出switch是兼容了枚举的发现传进来的是枚举类型sex 下面的case都不需要Constant2.BOY也不会报错(其他地方还是需要.BOY的)如果是密码之类的 具体的数据的值 可以用常量(有内容)枚举毕竟还是一个对象 是引用类型的 是一个表示信息的对象(上下左右)五、抽象类和抽象方法5.1 基本介绍抽象方法只能有方法签名 不能有具体的方法实现(方法体)子类继承了抽象类之后子类一定要重写抽象类的抽象方法一般抽象类就是去给子类继承的5.2 基本使用类是对象的完整的设计图纸 抽象类可以理解为不完整的设计图纸所以抽象类的作用就是给子类继承 然后让子类去完善图纸 再得到一个完整的设计图纸5.3 案列–加油卡银卡有很多类似的属性 但是支付这个行为 又各不相同所以抽离一个银行卡父类 让支付方法成为抽象方法 不同的子类去实现需要的支付方式5.4 抽象类的特征和注意事项类的五大成分:成员变量 构造器 方法 代码块 内部类abstract只能修饰类和成员方法既然是抽象的 那肯定不能实例化(形象化) 也就是不能new 抽象类()5.5 为什么抽象类(不管里面有没有抽象方法)都不能实例化?如果有抽象方法没抽象方法 为什么也不行呢?5.6 abstract和final的关系final修饰的类–不准被继承(最终类);abstract修饰的类–你不去继承就失去意义了(必须要被继承)final修饰的方法–不准被重写(最终方法);abstract修饰的方法–抽象方法 子类必须重写每个父类的抽象方法abstract final void run();final不让重写 abstract一定要重新 矛盾了5.7 总结1.抽象类/成员方法 都是用关键字abstract修饰(abstract不能修饰变量 代码块 构造器)2.抽象方法不能有具体的方法体3.一个类中如果有抽象方法 那么它必须声明成抽象类(所以抽象类不一定有抽象方法 但是有抽象方法的类一定是抽象类)4.抽象类一般都是作为父类他里面除了有公共的代码 最主要的就是他确定某些行为子类肯定有但是不同的子类具体又不一样 这些东西就被定义成抽象方法相当于提供了一个完成了一部分的图纸 完整的图纸交给子类去完成5.一个类如果继承了一个抽象类 那么它必须要实现所有的抽象方法 一旦有抽象方法没有被实现 那么这个子类也必须被定义成抽象类好让孙子类去继续实现 以此类推6.抽象类不能被实例化不能new 抽象类()六、接口6.1 什么是接口JDK8之前 接口中只能是抽象方法(public abstract) 或者 常量(public static final)接口体现一种规范约束他人必须这么设计 而规范一定是公开的(public)在IDEA里它认为可以省略的都是标灰的刚刚写的public等都是灰色的 说明默认是public的下图写的如果是public void run() 默认也是public abstract void run()6.2 接口对类的规范约束:被类实现(多实现)一个实现类可以实现单个接口 也可以同时实现多个接口实现类中 一定要重写所有接口规定的所有抽象方法 否则实现类需要定义为抽象类实现类必须重写接口所有的抽象方法否则实现类需要定义为抽象类(相当于继承了抽象方法rule())一般实现类肯定是要重写接口的抽象方法而不是去定义成抽象类6.3 接口多继承的作用:规范合并类和类的关系是:单继承类和接口的关系是:多实现接口和接口的关系是:多继承 一个接口可以同时继承多个接口下图问题所在:接口可以多继承合并所有接口到SportMan接口:6.4 JDK8开始:接口新增方法介绍为什么新增方法?为了丰富接口的同时不需要再对实现子类进行修改主要是学习语法默认方法实际上就是普通实例方法(不想推翻一开始设计接口的理念-永远不会写具体的方法 只约束好规范 所以加了一个默认方法的概念)需要用接口的实现子类的对象来调用静态方法必须而且只能用接口名.静态方法调用(其实是为了保持接口能多实现的特性)私有方法私有实例方法 必须在接口内部被其他的私有方法或者默认方法访问私有的东西只能在本类(本接口)内部访问6.5 使用接口的注意事项1.接口不能创建对象(没有构造器)它就是一种规范 是一种更加彻底的抽象接口和抽象类都不能直接new对象(抽象和规范都不能形象化 这个观点不能动摇)2.就理解为什么静态方法必须用接口名.静态方法来调用了为什么要这样设计-为了能够保持接口多实现接口A.test 或者 接口B.test都没问题如果允许实现子类C.test() 那就不知道调用哪个test了3.一个类只能有一个亲爹(类单继承) 但是可以有若干个干爹(接口多实现) 但是优先听亲爹的看下面两行代码 会发现设计师很巧妙(也是先继承亲爹 再认了个干爹 亲爹优先)class Cat extends Animal implements Food(正确)class Cat implements Food extends Animal(error)4.我们已经知道 类不能多继承就是因为调用父类重名的方法不知道调用谁 但是为了保持接口支持多实现的特性特殊给他搞了这个语法CC实现子类对象如果调用go()肯定有问题 有两个go() 不知道调谁那就强制CC实现子类重写go() 再去调用的时候 根据就近原则就调用CC子类重写的但是这样子以后永远都用不了AA和BB的go()实际开发不太可能使用(单纯是设计者在圆场)5.多继承的时候 规范合并不能冲突假如允许下图这种写法那么CCC的实现子类肯定要重写int run() 和 void run() 但是这俩方法无法构成重载(而是方法重定义) 肯定要报错如果不冲突就可以完成多继承假如规范合并完之后 run()能构成重载的话也不冲突 那就可以这样多继承七、多态7.1 基本介绍猫和狗都是同类型的对象(动物类Animal的对象)但是猫和狗同样是run()的行为 特征却不一样多态的前提:再解释一下为什么要有方法重写方法重写肯定是方法名相同(也就是同一个行为) 再结合左编译右运行就体现出同(编译)类型的对象执行同一个行为(父类或者编译类型的方法) 表现出不同的行为特征(子类或者运行类型方法重写)7.2 向上转型(自动类型转换)a.run() 或者 a1.run()在编译阶段(写代码的时候 能不能调用run) 看左边的类型真正运行起来 还是看右边的运行类型(有不同的运行类型) 这就体现出多态同样都是Animal类型的a和a1对象 都调用run() 但是具体执行结果却不一样(运行类型都重写了run方法)左编译 右运行(同一类型对象 不同行为特征)7.3 多态的优缺点解耦合玩具车的电池或者轮子不能用 随时卸了换别的 车 电池 轮子之间其实就解耦合了明显强耦合不好解耦合好 容易拖展维护 做软件也是如此换右边new出来的对象 就跟换零件一样下面的代码都不需要改 run()功能就被更新成Dog类的了易拓展定义方法参数列表的时候使用父类类型作为参数的类型该方法就可以接收所有的子类对象体现出多态的拓展性下图a.run() 执行的是a运行类型的run(也就是子类重写的run) a.run()也发生了左编译右运行注意:多态是一种特征 我们直接用这种风格形式就行了 显得更专业下图就不需要定义成Dog d 直接就使用多态的形式来定义不能调用子类独有方法(向下转型可以解决此问题)编译阶段(写代码的时候) 能调用到什么方法 看的是编译类型(左边父类)如下图 父类Animal有run的行为是合理的但是看门的行为 应该是狗狗特有的方法 那么如果编译类型是Animal 就无法调用到子类特有看门方法7.4 向下转型(强制类型转换)可以转换成真正的子类类型 从而调用子类的独有功能下图的强转编译阶段不会报错(有继承关系/实现关系的2个类型就可以强转 编译不报错) 但是运行阶段可能报错对象变量名 instanceOf XXX类型:判断某个对象的运行类型是否为XXX类型或者XXX类型的子类是则返回true7.5 综合案列:设计一个电脑对象八、内部类8.1 内部类的使用场景类的五大成分:变量 方法 构造器 代码块内部类8.2 静态内部类(了解)静态内部类属于外部类本身具体使用和普通类十分相似特点:记住静态的 都是属于类的(这里是属于外部类)1.静态内部类 和 外部类的静态成员 相当于都是属于外部类本身的所以可以访问2.外部类的实例成员是属于具体对象的 有类不一定有对象 所以在静态内部类无法直接访问(可以在静态内部类里面创建Outer的对象来间接访问)总结:8.3 成员/实例内部类(了解)没有static修饰属于外部类的对象先有外部类对象 才会有内部类对象因为实例内部类是属于外部类的对象 所以一定现有外部类对象 才会有内部类对象new Outer()就是先有了外部类对象 才能再new内部类对象特点:1.记住成员内部类属于外部类的对象有了对象一定有类了 而static修饰的就是属于类的2.有了成员内部类对象 就一定有了外部类的对象外部类的实例成员自然也有了在成员内部类中外部类名.this 就找到了外部类对象8.4 局部内部类(了解)就是定义在局部范围内的类局部内部类的作用范围 就是局部范围的 所以用public修饰局部内部类报错而且以前接口也不让定义在局部 接口是公开的规范 新版JDK16把这些语法全都开放了8.5 匿名内部类(重点掌握)基本介绍本质也是一个局部内部类是一个类 但他同时也是该匿名内部类的一个对象重点:类对象为一体(匿名内部类写出来就会产生一个匿名内部类的对象)代码案例匿名内部类写出来就会产生一个匿名内部类的对象匿名内部类的对象类型 相当于是当前new的那个类型的子类类型下图在new Animal 那么这个匿名内部类的对象的类型相当于Animal的子类类型右边那一坨写出来 就随之创建出了匿名内部类的对象了 注意不是Animal的对象(Animal是抽象类 不可能new对象)而且匿名内部类的对象的类型 就是Animal的子类类型匿名内部类的.class文件都没有名字 那么有没有class文件呢?前面已经说过 匿名内部类也是一种特殊的局部内部类本质也是一个局部内部类$1说明是第一个匿名内部类的.class文件匿名内部类常见使用形式也是在讲语法 看如下需求不使用匿名内部类的话 通常会这么写(多态的形式 编译类型用父类或者接口 运行类型用子类或者实现子类):注意接口也是父类 算干爹类 他的子类都叫做实现子类使用匿名内部类的写法:对象回调了(我把这个匿名内部类对象送给别人(s)了 但是最后又调用了原本对象里的方法)如果老师也来游泳 这几行代码就够了匿名内部类可以作为方法的实际参数进行传输简化写法–匿名对象直接作为方法入参(这个参数的类型就是那个匿名内部类本身类型)这其实也体现了多态(编译类型用的是接口)匿名内部类真实案例与简化代码下面这个匿名内部类 就是在监听有没有鼠标点击 点击了做出反应还可以简化:前面的简化:总结外部类只能用public和默认来修饰而四个访问修饰符 都可以修饰内部类九、Lambda表达式9.1 函数式接口注意:只能简化函数式接口的匿名内部类错误示范 因为Animal不是函数式接口9.2 基本使用通过匿名内部类创建匿名内部类对象:匿名内部类对象直接作为函数参数:9.3 简化的案例Comparator是一个函数式接口 所以可以简化ActionListener是一个函数式接口 所以可以简化9.4 省略规则(进一步简化)注意第二个规则 是针对一个参数的情况如果没有参数 ()就不能省略案例1:案例2:案例3:9.5 总结遇到了函数式接口再简化 否则不要强行简化