目录
面向对象复习补漏
类就是设计图
类就是建造对象的蓝图。
定义类的注意事项:
- 类名建议首字母大写。满足驼峰模式。
- 一个java文件中可以定义多个类,但是只能有一个类是用public修饰的,public修饰的类名必须成为Java代码的文件名称。
- 按照规范:建议一个Java文件只定义一个类。
构造器
1.构造器的作用?
初始化类的对象,并返回对象的地址。
2.构造器有几种,各自的作用是什么?
无参数构造器:初始化的对象时,成员变量的数据均采用默认值。
有参数构造器:在初始化对象的时候,同时可以为对象进行赋值。
3.构造器有哪些注意事项?
任何类定义出来,默认就自带了无参数构造器,写不写都有。
一旦定义了有参数构造器,无参数构造器就没有了,此时就需要自己写无参数构造器了。
this关键字
this关键字出现在成员方法、构造器中、代表当前对象的地址。用于指定访问当前对象的成员变量、成员方法。
this关键字小结
面向对象的三大特征:封装、继承、多态。
- 封装:解决属性和方法属于哪个对象的问题。
- 封装步骤:通常将成员变量私有、提供方法进行暴露。
- 封装作用:提高业务功能设计的安全性,提高开发效率。
特征的含义:
- 所谓特征指的是已经成为Java设计代码的基本特点,即使毫无意义,通常也要需要满足这样的设计要求来编写程序。
如何进行更好的封装?
- 一般会把成员变量使用private隐藏起来,对外就不能直接访问了。
- 提供public修饰的getter和setter方法暴露其取值和赋值。
标准JavaBean
- 也可以理解成实体类,其对象可以用于在程序中封装数据。
Java中书写标准JavaBean必须满足如下要求:
- 成员变量使用private修饰。
- 提供每一个成员变量对应的setXxx()/getxxx()。
- 必须提供一个无参构造器。
工具类
为什么工具类中的方法不用实例方法做?
- 实例方法需要创建对象调用。
- 此时用对象只是为了调用方法,这样只会浪费内存。
工具类定义时的其他要求:
由于工具里面都是静态方法,直接用类名即可访问,因此,工具类无需创建对象,建议将工具类的构造器进行私有化。
小结
代码块
作用:
初始化静态资源
初始化实例资源
案例:制作一副扑克牌
放到main里也可以,但是这种静态代码块的写法更专业,彰显牛逼
设计模式
什么是设计模式(Design pattern)
- 开发中经常遇到一些问题,一个问题通常有n种解法的,但其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
- 设计模式有20多种,对应20多种软件开发中会遇到的问题。
- 学设计模式主要是学2点:
>第一:这种模式用来解决什么问题。
>第二:遇到这种问题了,该模式是怎么写的,他是如何解决这个问题的。
单例模式
·可以保证系统中,应用该模式的这个类永远只有一个实例,即一个类永远只能创建一个对象。
·例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。
饿汉单例,设计步骤:
创建一个类,把构造器私有,外部不可以创建新对象。
定义一个静态成员变量来存储对象。
包
l包是用来分门别类的管理各种不同类的,类似于文件夹、建包利于程序的管理和维护
l建包的语法格式:package 公司域名倒写.技术名称。包名建议全部英文小写,且具备意义
package com.itheima.javabean;
public class Student {
}
建包语句必须在第一行,一般IDEA工具会帮助创建
导包
- 相同包下的类可以直接访问,不同包下的类必须导包,才可以使用!导包格式:import包名.类名;
- 假如一个类中需要用到不同类,而这个两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名(全名)访问。
什么是权限修饰符?
- 权限修饰符:是用来控制一个成员能够被访问的范围。
- 可以修饰成员变量,方法,构造器,内部类,不同权限修饰符修饰的成员能够被访问的范围将受到限制。
权限修饰符的分类和作用范围
学完权限修饰符需要具备如下能力
- l能够识别别人定义的成员的访问范围。
- l自己定义成员(方法,成员变量,构造器等)一般需要满足如下要求:
- 成员变量一般私有。
- 方法一般公开。
- 如果该成员只希望本类访问,使用private修饰。
- 如果该成员只希望本类,同一个包下的其他类和子类访问,使用protected修饰。
final关键字的作用
final 关键字是最终的意思,可以修饰(类、方法、变量)
- l修饰类:表明该类是最终类,不能被继承。一般不用,工具类可以加final,使用的不是继承的。
- l修饰方法:表明该方法是最终方法,不能被重写。一般不加,//TODO
- l修饰变量:表示该变量第一次赋值后,不能再次被赋值(有且仅能被赋值一次)。
补充:变量分为局部变量(初始化一个值后续不可修改)
成员变量,成员变量又分为
实例成员变量(几乎不用,会导致所有实例的数据一样的)
静态成员变量。
final修饰变量的注意
- final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。
- final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的。
常量
- 常量是使用了public static final修饰的成员变量,必须有初始化值,而且执行的过程中其值不能被改变。
- 常量名的命名规范:英文单词全部大写,多个单词下划线连接起来。
- 常量的作用:通常用来记录系统的配置数据。
使用常量做信息配置的优势
- 在编译阶段会进行“宏替换”:把使用常量的地方全部替换成真实的字面量。相当于不再重新使用常量来替换,直接用字面值。
- 维护系统容易,可读性更好。
案例说明:
现在开发的超级玛丽游戏需要接收用户输入的四个方向的信号(上下左右),以便控制玛丽移动的方向。
选择常量做信息标志和分类:
代码可读性好,实现了软编码形式。
相比于在程序中使用1234,使用常量来做信息标志,使程序的可读性可维护性更好。类比#define
枚举
public enum Season {
//第一行必须罗列枚举类的对象名称,建议全大写
SPRING, SUMMER, AUTUMN, WINTER;
}
反编译之后:
枚举的特征:
- 枚举类都是继承了枚举类型:java.lang.Enum
- 枚举都是最终类,不可以被继承。
- 构造器都是私有的,枚举对外不能创建对象。
- 枚举类的第一行默认都是罗列枚举对象的名称的。每个对象名称都是常量,写四个对象就只有四个对象。
- 枚举类相当于是多例模式。
案例说明:
现在开发的超级玛丽游戏需要接收用户输入的四个方向的信号(上下左右),以便控制玛丽移动的方向。
选择常量做信息标志和分类:(实际开发中这种方式相对更多)
虽然可以实现可读性,但是入参值不受约束,代码相对不够严谨。
枚举做信息标志和分类:
代码可读性好,入参约束严谨,代码优雅,是最好的信息分类技术!建议使用!
switch已经兼容枚举,可以直接读取枚举类型。
static关键字
- static是静态的意思,可以修饰成员变量和成员方法。
- static修饰成员变量表示该成员变量只在内存中只存储一份,可以被共享访问、修改。
静态区的变量各个成员实例都可以访问
成员方法的分类
静态成员方法(有static修饰,归属于类),建议用类名访问,也可以用对象访问。
实例成员方法(无static修饰,归属于对象),只能用对象触发访问。
对象自己用的方法定义成实例方法,共用性的方法定义成static方法
小结
方法的内存原理
第一步,将类和静态方法加载到方法区,
第二步,将main提到栈区跑,此时可以直接调用其他static方法,
第三步,创建实例,放入堆内存,访问方法区,可以调用静态和对应的非静态方法。
static使用注意事项
- 静态方法只能访问静态的成员,不可以直接访问实例成员。
- 实例方法可以访问静态的成员,也可以访问实例成员。
- 静态方法中是不可以出现this关键字的。
抽象类
抽象方法,不实现,只作方法签名,不声明方法体。
一个类里如果有抽象方法,这个类也要声明为抽象类。
派生出子类,要子类去完成这个方法
- 抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承。
- 当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成。此时这个类就可以声明成抽象类。
也可以定义一些子类通用的实例变量,提升代码复用性
抽象类小结
注意:
- 类有的成员(成员变量、方法、构造器)抽象类都具备
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。(实际应用中这一条很少见)
- 不能用abstract修饰变量、代码块、构造器。
- 抽象类不能创建对象,即使内部没有抽象方法的抽象类也不能创建对象!
final和abstract有什么关系?
互斥关系:
final修饰的类不能被继承,abstract修饰的类往往需要被继承并实现方法。
修饰的方法同上,一个不能被重写,一个必须被重写。
模板方法
什么时候使用模板方法模式?
- 使用场景说明:当系统中出现同一个功能多处在开发,而该功能中大部分代码是一样的,只有其中部分可能不同的时候。
模板方法模式实现步骤:
- 把功能定义成一个所谓的模板方法,放在抽象类中,模板方法中只定义通用且能确定的代码。
- 模板方法中不能决定的功能定义成抽象方法让具体子类去实现。
案例,写作文
标题和首尾段是确定的,要求不同的学生类自己发挥正文部分
中学生类继承学生类,来实现具体的写正文方法
使用时:调用父类模板方法,遇到抽象的writemain(),再调子类的具体实现的方法。
注意:模板方法应该用final来修饰,使其不能被重写。
接口
就是一种规范,约束必须要这么做,且一定是公开public的。
由于接口体现规范思想,必须公开,所以代码中public abstract可以省略。
接口与类的关系:
接口是用来被类实现(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类。
一个类只能继承一个父类,但可以同时实现很多个接口。
接口多继承:一个总接口继承其他很多的接口,实现类只需要继承这个总接口即可。
接口新增的方法
JDK8之后,接口新增3个方法。可以直接在接口中定义带有方法体的方法,便于实现类直接获得,方便扩展。
默认方法实际上就是实例方法,用实现类的实例对象来调用。用得不多,为看源码做准备。
只能接口名自己调用Interface.inAddr();
JDK9之后才有的私有方法
技巧:在project struture里修改JDK版本,可以查看该版本是否支持某项技术
外部不可用,为接口中的其他方法所用。
接口的注意事项:
- 接口不能创建对象,它是抽象中的抽象
- 一个类实现多个接口,多个接口的规范不能冲突
- 一个类实现多个接口,多个接口中有同样的静态方法不冲突。
只能A接口调A的静态方法,B接口调B的静态方法。
- 一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的。
class Cat extends Animal implements Creature { }注意只能先extens,再implements
- 一个类实现了多个接口,多个接口中存在同名的默认default方法,可以不冲突,这个类重写该方法即可。
- 一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承。
多个接口的抽象方法不一致,比如一个返回String ,一个返回Void。
总结:
定义接口,实现功能,项目中的软件解耦。
多态
多态重点:编译看左边,运行看右边。编译阶段对象属于父类类型,运行调方法时实际上还是子类的方法。
劣势:多态形式下,不可以调用子类独有的方法(如果要用需要强转)
调用前可以使用强转,再使用子类方法。
强转之前最好用instanceof判断类型,得到其真实类型。
内部类
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计。
- 内部类通常可以方便访问外部类的成员,包括私有的成员。
- 内部类提供了更好的封装性,内部类本身就可以用private、protectecd等修饰,封装性可以做更多控制。
重点:匿名内部类
静态内部类
在创建对象的时候,需要带上外部类的类名
静态内部类可以访问所在外部类的静态成员变量
不可以访问外部类的实例成员变量
静态内部类小结
成员内部类
创建方式要注意,要先把外部类给new出来之后,再紧跟着new内部类:new Outer().new Inner()
注意:
1、成员内部类中是否可以直接访问外部类的静态成员?
可以,外部类的静态成员只有一份可以被共享访问。
2、成员内部类的实例方法中是否可以直接访问外部类的实例成员?
可以的,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员。
成员内部类变量访问范围的Demo
show方法里的局部变量可以直接访问,内部类中的成员变量要加this访问,所属的外部类的成员变量加 类名.this来访问。
局部内部类(了解即可)
写法很奇怪
匿名内部类
- 匿名内部类是一个没有名字的内部类。
- 匿名内部类写出来就会产生一个匿名内部类的对象。
- 匿名内部类的对象类型相当于是当前new的那个的类型的子类类型。
匿名内部类用法,抽象类本来不可以创建对象,但是加一对大括号{}马上重写其方法,就可以实现简化代码,不需要再创建一个子类继承该抽象类。可以说是类和对象混合在一起。
注意:这个对象a是匿名内部类(继承Animal)的对象,而不是接口的对象。
简化代码:直接将匿名内部类对象作为方法的入参,参考Btn按钮的setOnClickListener里的new OnClickListener
常用API
Object类
toString()直接用是没意义的,需要重写来打印内容。
equals( )
默认比较两个对象的地址,一般需要子类重写,来比较内容。
注意:字符串用equals来比较是比较内容的。而用"=="是比较地址的
小结:
Objects的equals方法,会先做一层非空校验。比直接用object的equals更安全,因为equals传入null的话,会有空指针异常。
小结
StringBuilder
StringBuilder提供的常用api方法:
StringBuilder的append方法拼接完之后,又返回了同一个this对象,所以支持链式编程。
注意,其reverse方法,反转的是本字符串的所有内容,而不是以每次append作为基本单位。
//"国中你爱我cba110"
注意:StringBuilder只是拼接的手段,最后的目的还是要恢复成String类型的对象。
StringBuilder效率高的原因
小结:
Demo:用StringBuilder来输出整型数组的内容:
代码风格学习:结尾处用三目运算符来一步兼容中间符号插入和结尾处理,注意右中括号不可以放在循环里,否则空数组的情况只会打印一个左中括号。
Math类
工具类,没有构造器,不能创建对象,内部的方法均为静态static方法。
常用:random,取绝对值,,,,等等。
random方法,生成0-1之间的随机数,含0不含1,如果要生成其他区间,可以以此为基础来变通。
System类
第一个终止当前虚拟机,慎用!
第二个获取系统当前时间,从1970年1月1日(纪念C语音的生日)开始计算,到某一时刻的毫秒值。可以用作性能分析,在某一板块开始和结束时都获取一下当前时间作差,得到程序运行耗时。
arraycopy,数组复制,参数很多,建议用的时候看源码,对应填入参数。
BigDecimal
解决浮点型运算精度失真问题,后续用到再学习,黑马视频强化课,day3最后一个视频。
Date类
无参构造器或者long型的有参构造器,传入毫秒值。
时间格式化的方法
两个小算法
选择排序
选择排序的思想
·每轮选择当前位置,开始找出后面的较小值与该位置交换。
选择排序的关键
·确定总共需要选择几轮:数组的长度-1.
·控制每轮从当前位置为基准,与后面元素选择几次。
二分查找
只适用排好顺序的数组,性能较好。
小结:
Lambda表达式
- Lambda表达式是JDK8开始后的一种新语法形式。
- 作用:简化匿名内部类的代码写法。
只能简化函数式接口的匿名内部类
什么是函数式接口?
- 首先必须是接口、其次接口中有且仅有一个抽象方法的形式
- 通常我们会在接口上加上一个@Functionallnterface注解,标记该接口必须是满足函数式接口。
例子:
小结
Lambda进一步省略代码:
Lambda表达式的省略写法(进一步在Lambda表达式的基础上继续简化)
- 参数类型可以省略不写。
- 如果只有一个参数,参数类型可以省略,同时()也可以省略。
- 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
- 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";”不写
注意:简化不要强行过度简化,保留一些代码可读性。
包装类
int 变成Integer,char变成Character,其他类型均是首字母大写。
第二条用的不多,可以直接使用 基本类型+""
第三条用得很多,将字符串转换成其真实的类型。
要转成什么类型就调对应包装类的方法。
或者直接用ValueoOf方法