- 快速写好for循环定义
- 不是基本类型的数据都是引用类型string
-
byte short int(默认)long整型
- byte 字节型占1个字节 -128 -127
- short 短整型占2个字节
- int 整型 默认类型 占4个字节
- long 长整型 占8个字节 如果希望当成长整型需要在后面加L/l;
long lg=124673616571743182L
-
float double(默认)浮点型
- float 单精度占4个字节如果希望当成长整型需要在后面加F/f;
float score =98.5f
- float 单精度占4个字节如果希望当成长整型需要在后面加F/f;
-
char 字符型
-
boolean 布尔型
- byte short int long float double
-
char
-
必须单引号围起来
-
有且仅有一个字符
-
特殊字符
- /t空格
- /n换行
- 必须双引号围起来,内容可随意
- true
- false
-
数据类型 变量名称 = 初始值
- int age=21;
- double money=6.0
-
装数据的
-
里面的数据可以改变
- = 进行赋值,从右往左执行
- 什么类型变量存储什么类型字面值
- 同一个范围变量名不能重复
- 变量定义时可以不用赋初始值,在使用时要有初始值
- 变量存在访问范围,从定义开始到 } 截止
- a 97
- A 65
- 0 48
- 计算机要存字符但是不能直接存储字符,只能存储字符编号的二进制形式
-
字母,数字,下滑线,$符号组成的名称
-
硬性要求
- 不能数字开头
- 不能关键字开头
- 不能是特殊符号
-
推荐要求
- 变量名称:有意义,全英文,首字母小写,满足驼峰模式
- 类名称:有意义,全英文,首字母大写,满足驼峰模式
- 存在不同类型的变量赋值给其他类型的变量
- 范围小的变量可以直接给范围大的变量赋值
-
可以强行将类型范围大的变量,数据赋值给范围小的变量进行运算
- 可能出现数据丢失
- 小数强制转换成整数是直接截断小数保留整数
-
数据类型 变量 =(数据类型)变量,数据
- 小范围的类型会自动转换成大范围的类型运算
- 由最高类型决定
- byte short char 是直接转换成int 类型进行运算的
- 与字符串做+运算时会被当成连接符,结果是字符串
- 能算就算,不能算放一起做字符串
-
++,–如果在变量前后使用,并且包含其他操作,赋值或者在表达式中,放在前后有明显区别
- 变量前(++a)先进行+1,-1再拿变量值进行运算
- 变量后(a++)先拿变量值进行运算,再进行+1,-1
-
++,–单独使用无区别
-
扩展
-
+=
-
加后赋值
- a+=b等价于 a=(a的数据类型)(a+b);
-
-
-=
-
减后赋值
- a-=b等价于 a=(a的数据类型)(a-b);
-
-
*=
-
乘后赋值
- a*=b等价于 a=(a的数据类型)(a*b);
-
-
/=
-
除后赋值
- a/=b等价于 a=(a的数据类型)(a/b);
-
-
%=
-
取余后赋值
- a%=b等价于 a=(a的数据类型)(a%b);
-
-
-
注意
- 扩展的赋值运算符隐含了强制类型转换
-
逻辑与"&"
- 有一个为false,结果就是false
-
短路与"&&"
- 一个为false,结果是false。前一个为false,后一个条件就不执行了
-
逻辑或"|"
- 有一个为true,结果就是true
-
短路与"||"
- 一个为true,结果是true。前一个为true,后一个条件就不执行了
-
逻辑非"!"
- !false=true,!true=false
-
逻辑异或"^"
- 相同是false,不同是true
-
注意
- 实际开发中常用逻辑运算符是:&&,||,!
-
作用
- 根据条件作出分支选择,返回对应值
-
格式
- 条件表达式? 值1:值2
-
使用场景
- 一般只有两种情况的时候使用三元运算符会简化代码(如只有一个if eles语句)
- 最高优先级是()
-
Java写好的程序,可以直接调用
-
键盘录入开发步骤
- 导包:import java.util.Scanner;
- 抄写代码得到扫描器对象:Scanner sc=new Scanner(System.in)
- 抄写代码等待接收用户输入的数据:sc.nextInt(),sc,next()
-
随机数开发步骤
-
导包:import java.util.Random;
-
Random r = new Random();
-
int number = r.nextInt(10)
-
注意
-
括号中的范围是【0-10)包左不包右,Java中大部分的范围规则都是包左不包右
-
可用加减法进行范围扩展得到所需范围
- 例:生成65-91之间的随机数
- 65 - 91=>(0-26)+65;减加法先减算出插值,在加上减数,注意包左不包右,所以括号要加1
- int number = r.nextInt(27) + 65;
-
-
-
object类
-
作用
- 一个类要么默认继承了Object类,要么间接继承了Object类,Object类是java中的祖宗类
- Object类的方法是一切子类都可以直接使用的
-
常用方法
-
public String toString()
- 默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址(一般不重写的话可以省略不写)例:System.out.println(s)等同于System.out.println(s.toString());
- 父类的toString方法存在的意义就是被子类重写,以便返回对象的内容信息,而不是地址信息
-
public Boolean equals(Object o)
- 默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false(可以用“==”替代)
- 父类equals方法存在的意义也是被子类重写,以便子类自己来定义比较规则
- 官方在进行字符串比较时没有用对象自己的equals方法,而是选择了Objects(与Object类还是继承关系,jdk1.7以后才有)的equals方法比较结果一样,更安全
-
Objects常见方法
-
public static boolean equals(Object a,Object b)
-
比较两个对象的,底层会先进性非空判断,从而可以避免空指针异常。再进行equals比较
-
源码
- public static boolean equals(Object a,Object b){return (a==b)||(a!=null&&a.equals(b));}
-
-
public static boolean isNull(Object obj)
- 判断变量是否为null,为null返回true,反之
-
-
-
-
StringBuilder类
-
是一个可变的字符串类,我们可以把它看成是一个对象容器
-
作用
-
提高字符串的操作效率,如拼接,修改
- String s1=“a”;String s2=s1+“b”;
- 一个加号,堆内存中两个对象,而StringBuilder将字符串存在常量池中,只在创建对象的时候有一个对象
-
-
构造器
-
public StringBuilder()
- 创建一个空白的可变字符串对象,不包含任何内容
-
public StringBuilder(String str)
- 创建一个指定字符串内容的可变字符串对象
-
-
常用方法
-
public StringBuilder append(任意类型)
- 添加数据返回StringBuilder对象本身
-
public StringBuilder reverse()
- 将对象内容反转
-
public int length()
- 返回对象内容长度
-
public String toString()
- 通过toString()就可以实现把StringBuilder转换为String
-
支持链式编程,例:sb1.append(“a”).append(“b”)append(“c”).reverse();
-
-
与String的区别
-
String
-
内容是不可变的,拼接字符串性能差
- 定义字符串使用String
-
-
StringBuilder
-
内容可变,拼接字符串性能好,代码优雅
- 拼接,修改字符串等操作使用StringBuilder
-
-
-
-
Math类
-
包含执行基本数字运算的方法,Math类没有提供公开的构造器
-
如何使用类中的成员
- 看类的成员是否都是静态的,如果是,通过类名就可以直接调用
-
常用方法
-
public static int abs(int a)
- 获取参数绝对值
-
public static double ceil(double a)
- 向上取整
-
public static double floor(double a)
- 向下取整
-
public static int round(float a)
- 四舍五入
-
public static int max(int a,int b)
- 获取两个int值中较大的值
-
public static double pow(double a,double b)
- 返回a的b次幂
-
public static double random()
- 返回值为double的随机值,范围[0.0,1.0)
-
-
-
System类
-
System的功能是通用的,都是直接用类名调用即可,所以System不能实例化
-
常用方法
-
public static void exit(int status)
- 终止当前运行的Java虚拟机,非零表示异常终止
-
public static long currentTimeMillis()
-
返回当前系统的时间毫秒值形式
- 计算机认为时间有起点的起始时间:1970年1月1日 00:00:00
- 时间毫秒值指从1970年1月1日走到此刻的总毫秒值。1s=1000ms
-
进行性能分析
-
-
public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数)
- 数组拷贝
-
-
-
BigDecimal类
-
使用步骤
-
创建对象BigDecimal封装浮点型数据(最好的方式是调用方法)
- public static BigDecimal valueof(double val):包装浮点数成为BigDecimal对象
-
-
常用api
-
public BigDecimal add(BigDecimal b)
- 加法
-
public BigDecimal subtract(BigDecimal b)
- 减法
-
public BigDecimal multiply(BigDecimal b)
- 乘法
-
public BigDecimal divide(BigDecimal b)
- 除法
-
public BigDecimal divide(另一个BigDecimal对象,精确几位,舍入模式)
-
除法
- BigDecimal c11=a11.divide(b11,2,RoundingMode.HALF_UP);
-
-
-
注意
-
禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象
-
BigDecimal(double)存在精度损失风险
- BigDecimal g=new BigDecimal(0.1F);实际存储值为0.10000000149
-
-
优先推荐入参为String的构造方法,或使用BigDecimal的valueOf方法,此方法内部其实执行了Double的toString,而Double的toString按double的实际能表达的精度对尾数进行了截断
- BigDecimal recommend1=new BigDecimal(“0.1”);
- BigDecimal recommend2=BigDecimal.valueOf(0.1);
-
-
作用
- 解决浮点型运算的精度失真问题
-
-
Date类
-
Date类的对象在Java中代表的是当前所在系统的此刻日期时间
-
构造器
-
public Date()
- 创建一个Date对象,代表的是系统当前此刻日期时间
-
public Date(long time)
- 把时间毫秒值转换成Date日期对象
-
-
常用方法
-
public long getTime()
- 获取时间对象的毫秒值
-
public void setTime(long time)
- 设置日期对象的时间为当前时间毫秒值对应的时间
-
-
记录时间的两种形式
-
日期对象
- 创建一个日期对象代表了:当前系统的此刻日期时间对象
- Date d=new Date();
- System.out.println(d);
-
时间毫秒值
- 获取当前的时间毫秒值
- long time=d.getTime();
- System.out.println(time);
-
-
-
SimpleDateFormat类
-
作用
- 可以对Date对象或时间毫秒值格式化成我们喜欢的时间形式
- 也可以把字符串的时间形式解析成日期对象
-
构造器
-
public SimpleDateFormat()
- 构造一个SimpleDateFormat,使用默认格式
-
public SimpleDateFormat(String pattern)
- 构造一个SimpleDateFormat,使用指定的格式
-
-
格式化方法
-
public final String format(Date date)
- 将日期格式化成日期/时间字符串
-
public final String format(Object time)
- 将时间毫秒值格式化成日期/时间字符串
-
-
对应关系
-
y-年
-
M-月
-
d-日
-
H-时
-
m-分
-
s-秒
-
例
- 2020-11-11 13:27:06-yyyy-MM-dd HH:mm:ss
- 2020年11月11日 13:27:06-yyyy年MM月dd日 HH:mm:ss
-
-
解析字符串成为日期对象
-
public Date parse(String source)
-
从给定的字符串开始解析文本以生成日期
- String dateStr=“2020年11月11日 13:27:06”;
- SimpleDateFormat sdf=new SimpleDateFormat(“yyyy年MM月dd日 HH:mm:ss”);
- Date d=sdf.parse(dateStr);
-
-
-
-
Calendar类
-
if
-
作用:根据条件有选择的执行代码
-
格式
-
if(条件)(执行代码)
-
注意
- 如果{}中只有一行代码,可以省略{}不写,不建议省略
- 只能执行一个分支
-
-
if(条件1){执行代码}else{其他代码}
-
if(条件1){执行代码1}else if(条件2){执行代码2}…else{其他代码}
-
-
-
switch
-
switch(表达式){
case 值1:
执行代码;
break;}
case 值n-1:
执行代码;
break;}
default:
执行代码; } -
表达式类型只能是byte,short,int,char,jdk5开始支持枚举,jdk7开始支持String,不支持double,float,long
-
case给出的值不允许重复,且只能是字面值,不能是变量
-
穿透性
- 如果case中没有写break,执行完这个case会直接往下一个case执行,不会判断了,直到遇到break截止
- 存在多个case分支的功能代码是一样时,可以用穿透性把流程集中到同一处处理,这样可以简化代码
-
注意别忘了分析所有情况都没有的情况放在default里
-
-
使用场景
-
switch分支结构
- 判断值匹配时
-
if分支结构
- 判断区间范围时
-
-
while
-
初始化语句
- while(循环条件){循环体语句(被重复执行的代码);迭代语句:}
-
-
do-while循环
-
先执行再判断
- 初始化语句:do{循环体语句;迭代语句;}while(循环条件)
-
注意:一定会先执行一次循环体
-
业务举例
- 抢票系统会先抢一次票再循环
-
-
for循环
-
用for循环求奇数和
- 方式一:for(int i =1;i <= 10; i++){if (int i % 2 == 1){}}
- 方式二:for (int i = 1; i <= 10; i +=2 ){}
-
for循环的格式
-
for(初始化语句:循环条件:迭代语句){循环体语句}
-
变为while循环
- for(:循环条件:){循环体语句;}
-
-
在用for循环时,控制内层循环何时需要返回值时,可以在内层循环外加信号位标记,一般信号位默认为true,当循环结束还为true时则记录该值
-
-
三种循环的差别
-
for和while是判断后执行;do -while是直接执行一次,再判断
-
for和while功能上没有任何区别,while能做的for一定能做
-
for的变量只能循环内部有效,while的变量从定义开始到循环体结束后还能被使用(一般在循环外定义变量)
-
使用关系
- 不知道次数的用while
- 知道次数的用for
-
-
死循环
- for(;{循环体代码;}
- while(true){循环体语句;}
- do{循环体语句;}while(true);
-
循环嵌套
- 形式:循环中又包循环
- for(int i = 0 ; i < 3 ; i++){for(int j = 0 ; j < 5 ; j++){循环体语句}}
- 外部循环每执行一次,内部循环全部执行完一次
-
continue关键字
- 跳出当前循环的当次执行,进入循环下一次
- 只能在循环中使用
-
break关键字
- 跳出并结束当前所在循环的执行
- 只能用于结束所在的循环,或者结束switch分支的执行
-
return关键字
- 无返回值时跳出并结束当前所在方法,有返回值时将返回值返回并结束当前方法
-
静态初始化写法
- 完整格式:数据类型[] 数组名 =new 数据类型[]{元素1,元素2,元素3…};
- 简化格式:数据类型[] 数组名 = {元素1,元素2,元素3…};
-
动态初始化写法
- 数据类型[] 数组名 =new 数据类型[长度];
-
使用场景
-
动态初始化
- 只指定数组长度,后期赋值,适合开始就知道数据的数量,但是不确定具体元素值的业务场景
-
静态初始化
- 开始就存入元素值,适合一开始就能确定元素值的业务场景
-
两种格式写法是独立的,不可以混用
-
-
基本类型
-
byte,short,char,int,long
- 0
-
float,double
- 0.0
-
boolean
- false
-
-
引用类型
-
类,接口,数组(数组嵌套),String
- null
-
- [I@4c873330; [:代表数组 I代表数组数据类型 @代表地址在哪
-
数组名称[索引]
-
数组的长度属性:length
- 最大索引表示方法:数组名.length -1;前提是个数大于0
- 数据类型[] 数组名 也可以写成 数据类型 数组名[]
- 什么数据类型就存储什么类型的数据,否则报错
- 数组一旦定义出来程序执行的过程长度和类型就固定了
- 如果访问元素位置超过最大索引,执行时会出现ArrayIndexOutOfBoundsException(数组索引越界异常)数组索引从0开始
- 如果数组变量中没有存储数组的地址,而是null,在访问数组信息时会出现NullPointerException(空指针异常)
-
数组求和
- 使用数组存储批量元素
- 遍历数组中每个元素然后求和
-
数组元素求最大值
- 使用数组存储数据
- 定义变量记录最大值,建议存储数组第一个元素为最大值,防止自定义的最大值比数组中元素最大值还大
- 遍历数组元素,如果该元素大于变量存储的元素值则替换
- 循环结束输出最大值即可
-
猜数字游戏
- 动态初始化数组存入5个随机的1-20之间的数据
- 定义一个死循环,不断才数据,遍历数组,判断是否在数组中,如果在结束死循环,否则继续
- 注意break只能跳出当前循环,要想跳出整个循环,可以给死循环定义名称,然后直接break 该名称;即可例:out: while(true){ for(;{
break out;}}
-
随机排名
-
定义一个动态初始化数组用于录入数据
-
遍历数组每个元素,每次随机一个索引值,让当前元素和该索引位置的元素进行交换
-
比那里输出数组元素内容即可
-
注意
- 交换需要定义一个临时变量来辅助
- 用Random方法随机索引值时括号里的范围最好填数组长度,方便以后数组长度改变时不用再逐一修改,可用性强
-
-
冒泡排序
-
思想
- 从头开始两两比较,把最大的元素与最小的元素进行交换
- 每轮把当前最大的一个元素存入到数组当前的末尾
-
步骤
- 定义外部循环,确认总共需要几轮比较:数组长度-1
- 定义内部循环,控制每轮依次往后比较几次:数组长度-i
- 如果当前位置的元素>后一个元素的元素值,两者交换
-
注意
- 如果外层循环从1开始则内层循环的循环条件是数组长度-i
- 如果外层循环从0开始则内层循环的循环条件是数组长度-i-1
-
-
注意事项
- 尽量用数组给的属性来代表变量,length
- 方法运行时所进入的内存,变量也是在这里
- new出来的东西会在这里开辟空间并产生地址
- 字节码(class)文件加载时进入的内存
-
形参
- 在方法定义时的变量
-
实参
- 在方法内部定义的变量
-
值传递,传输的是实参存储的值(方法中改变不了相当于拷贝)(如果传输的是地址则有可能会改变地址中的值,但是地址还是不变)
-
基本数据类型
- 传输的是存储的数据值
-
引用数据类型
- 传输的是地址值
-
-
同一个类中多个方法名称相同,形参列表不同
-
对于相似性业务场景:可读性好,方法名称相同提示是同一类型的功能,通过形参列表不同实现功能差异化的选择,这是一种专业的代码设计
-
识别技巧
- 只要同是一个类中,方法名称相同(区分大小写),形参列表不同,那么他们就是重载方法,其他都不管(修饰符,返回值类型都无所谓)
- 形参列表不同是指:参数的个数,类型,顺序不同,不关心参数的名称
-
重载方法中可以调用别的重载方法(例:传一个参数的可以调用传两个参数的方法,只需要给另一个参数赋值即可),减少代码量
- 如果方法声明了返回值类型,内部必须使用return返回对应类型的数据
- 方法不需要返回结果,返回值必须声明成void(无返回值类型),此时方法内部不可以使用(return返回数据)
- 形参列表可以有多个,甚至可以没有,如果有多个形参,多个形参必须用","隔开,且不能给初始值
- 方法要执行必须进行调用:方法名称(…)
- 方法编写顺序无所谓
- 方法和方法是平级关系,不能嵌套定义
- return语句下面不能写代码,永远无法执行无效代码
- 不调用就不执行调用必须严格匹配方法参数情况
- 有返回值的方法调用时可以定义变量接收结果,或者直接调用输出语句,甚至直接调用;无返回值的调用只能直接调用一下
- 一般功能性的代码都放在方法中方便后续调用
-
类是共同特征的描述
-
对象是真实存在的具体实例
-
如何得到对象
- public class 类名{1.成员变量(代表属性的,一般是名词)2.成员方法(代表行为的,一般是动词)}
- 类名 对象名 =new 类名();
-
拿到后能做什么
- 对象.成员变量
- 对象.成员方法
-
放在堆内存中
-
是引用类型,变量存储的是堆内存的地址
-
对象中,成员变量的数据放在堆内存中
-
-
注意事项
-
格式
- 修饰符 数据类型 变量名称 =初始化值;一般不用指定初始化值,存在默认值
-
类名首字母建议大写,具有意义,满足“驼峰模式”
-
一个Java文件中可以定义多个class类,且只能一个类是public修饰,而且public修饰的类名必须成为代码文件名。实际开发中建议还是一个文件一个class类
-
-
作用
- 用于初始化一个类的对象,并返回对象的地址
-
定义格式
- 修饰符 类名(形参列表){}
-
初始化对象格式
- 类型 变量名称 = new 构造器;
- Car c =new Car();
-
分类
- 无参构造器(默认存在的):初始化对象时,成员变量的数据均采用默认值
- 有参构造器:在初始化对象时,同时可以为对象进行赋值
-
注意
- 任何类定义出来,默认就自带了无参数构造器,写不写都有
- 一旦定义了有参数构造器,无参数构造器就没有了,此时就需要自己写无参构造器了
-
用来控制一个成员能够访问的范围
-
可以修饰成员变量,方法,构造器,内部类,不同权限修饰符修饰的成员能被访问的范围将受到限制
-
范围大小:private->缺省->protected->public
-
private
- 同一个类中
-
缺省
-
同一个类中
- 同一个包中其他类
-
-
protected
-
同一个类中
-
同一个包中其他类
- 不同包下的子类
-
-
-
public
-
同一个类中
-
同一个包中其他类
-
不同包下的子类
- 不同包下的无关类
-
-
-
-
-
要求
- 成员变量一般私有化
- 方法一般公开
- 如果该成员只希望本类访问,使用private修饰
- 如果该成员只希望本类,同一个包下的其他类和子类访问,使用protected修饰
-
final关键字
-
是最终的意思,可修饰方法,变量,类
-
修饰方法:表明该方法是最终方法,不能被重写
-
修饰变量:表示该变量第一次赋值后不能再被赋值(有且只有一次赋值)
- 基本不会修饰实例成员变量,无意义
- 修饰基本数据不能发生改变
- 修饰引用类型变量地址值不能发生改变,地址指向的内容可以改变
-
修饰类:表示该类是最终类,不能被继承
-
-
常量是使用public static final修饰的成员变量,必须有初始化值,而且在执行的过程中其值不可改变
-
好处
-
可以用于系统的配置信息,方便程序的维护,同时也能提高可读性
-
常量命名规范
- 英文单词全部大写
- 多个单词下划线连接起来
-
-
执行原理
- 在编译阶段会进行“宏替换”,使用常量把地方全部替换成真是字面量
- 好处是让使用常量的程序执行性能与直接使用字面量是一样的
-
是Java的一种特殊类型
-
作用
- 为了做信息标志和分类
-
格式
- 修饰符 enum 枚举名称{ 第一行都是罗列枚举类实例的名称 }
- enum Season{SPRING,SUMMER,AUTUMN,WINTER; }
-
特征
- 枚举类都是继承了枚举类型:java.lang.Enum
- 枚举都是最终类,不可被继承
- 枚举类的构造器都是私有的,枚举对外不能创建对象
- 枚举类的第一行默认都是罗列枚举对象的名称的
- 枚举类相当于是多例模式
-
使用场景
-
变量
- 具体值
-
枚举
-
做分类的时候
- 枚举是对象没有值
-
-
-
编译器会将枚举转换成常量定义,一般枚举的代码约束性好,入参值受控制,不像变量入参不受限制(例:调用方法时,传参可以写枚举中定义的名称,有效的防止代码漏洞)
-
某个父类知道其所有子类所要完成的某种功能,但是每个子类完成情况不一样,父类就只定义该功能的基本要求,具体由子类完成,这个类可以是一个抽象类,抽象类就是一种不完全的设计图,只给框架
-
必须使用abstract修饰
- 修饰符 abstract class 类名{}
-
抽象方法
- 就是抽象类中定义的子类必须完成的功能基本要求
- 修饰符 abstract 返回值类型 方法名称(形参列表);
- 没有方法体,只有方法签名,必须用abstract修饰
-
注意
- 一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法
- 或者这个类也定义成抽象类(再被其他子类继承重写抽象方法)
-
特征
-
有得有失
- 得到抽象方法,失去了创建对象的能力
-
为什么不能创建对象
- 类有的成员(成员变量,方法,构造器)抽象类都具有
- 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
- 一个类继承了抽象类必须重写完抽象类的所有抽象方法,否则这个类也要成为抽象类
- 不能用abstract修饰变量,代码块,构造器
-
final和abstract关系
-
互斥关系
-
abstract定义抽象类作为模板让子类继承,final定义的类不能被继承
-
抽象方法定义通用功能让子类重写,final定义的方法子类不能重写
-
模板方法建议用final
- 模板方法是给子类直接使用的,不让子类重写的,一旦子类重写了模板方法就失效了
-
-
-
格式
- 使用interface关键字来定义
- public interface 接口名{ //常量 //抽象方法}
-
特点
- jdk8之前接口中只能是抽象方法和常量,没有其他成分了
- 接口不能实例化(创建对象)
- 接口中的成员都是public修饰的,写不写都是,因为规范的目的是为了公开化
-
用法
- 接口是用来被类实现的,实现接口的类称为实现类,实现类可以理解成所谓的子类
- 修饰符 class 实现类 implements 接口1,接口2,接口3…{}
- 实现关键字:implements
- 从上面看出,接口可以被类单实现,也可以被类多实现
- 接口是干爹,实现类可有多个干爹,父类是亲爹,实现类只有一个亲爹
-
方法
-
默认方法
- 必须用default修饰
- 默认会用public修饰。需要用接口的实现类的对象来调用
-
静态方法
-
默认会public修饰,必须static修饰
-
注意
- 接口的静态方法必须用本身的接口来调用
-
-
私有方法
- 默认会public修饰,必须用private修饰,从jdk1.9才开始有的
- 只能在本类中被其他的默认方法或私有方法访问
-
-
注意
- 一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类
- 接口不能创建对象
- 一个类实现多个接口,多个接口中同样的静态方法不冲突
- 一个类实现了多个接口,多个接口存在同名的默认方法,不冲突,这个类重写该方法即可
- 一个接口继承多个接口是没问题的,如果多个接口存在规范冲突则不能多继承
-
this关键字
- 代表当前对象的地址(谁调用他就代表谁)(本类对象的引用)
- 可以用于访问当前对象的成员变量
-
super关键字
- 代表父类存储空间的标识
-
区别
-
this
-
this.成员变量,访问本类成员变量
-
this.成员方法(…)访问本类成员方法
- this(…)访问本类构造器
-
-
-
super
-
super.成员变量访问父类成员变量
-
super.成员方法(…)访问父类成员方法
- super(…)访问父类构造器
-
-
-
-
注意
- 子类通过this(…)去调本类的其他构造器,本类的其他构造器会通过super去手动调用父类的构造器,最终还是会调用父类的构造器
- 子类只会调用父类无参构造器,想要调用有参构造器用super
- this(…)和super(…)必须都只能放在构造器第一行,所以二者不能共存在同一个构造器中
-
封装
-
面向对象的三大特征之一(可以使用时尽量使用),合理隐藏,合理暴露
-
一般会把成员变量使用private隐藏起来
-
通过getter和setter方法暴露其访问
-
好处
- 加强了程序代码的安全性
- 适当的封装可以提升开发效率,同时可以让程序更容易理解和维护
-
-
继承
-
好处
- 继承是子类到父类的一种关系
- 提高代码复用性,减少代码冗余,增添类的功能扩展性
-
格式
- 子类 extends 父类
-
特点
-
子类继承父类,子类可以得到父类的属性和行为,子类可以用(可以继承父类的私有成员,但是不能直接访问)
-
子类能否继承父类的静态成员
- 个人认为不能因为静态成员是共享的子类可以直接访问,共享并非继承
-
子类不能继承父类的构造器,子类有自己的构造器,父类构造器用来初始化父类对象
-
子类所有构造器都会默认先访问父类中无参构造器,再执行自己
-
原因
- 子类在初始化的时候有可能会使用到父类中的数据,如果父类没有完成初始化,子类无法访问父类的数据
- 子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化(继承父类数据)
-
怎么调用的
- 子类构造器的第一行语句默认是super(),不写也存在
-
如果父类没有无参构造器会报错,需要手动书写super(…)手动调用父类的有参构造器
-
-
-
一个类只能继承一个直接父类
-
子类访问成员原则
-
就近原则
- 子类局部范围
- 子类成员范围
- 父类成员范围
-
出现重名的成员优先使用子类的,如果一定要用父类的可以用super关键字,指定访问父类成员
- super.父类成员变量/父类成员方法
-
-
Java中不支持多继承,但是支持多层继承
-
Java中所有类都是Object类的子类
-
Java中子类功能更强大
-
-
设计规范
- 子类们相同的特征(共同属性,共性方法)放在父类中定义
- 子类独有的属性和行为应该定义在子类自己里面
-
方法重写
-
在继承体系中,子类出现了和父类一摸一样的方法声明,我们就称子类的方法是重写方法
-
应用场景
- 当子类需要父类功能但父类该功能不能完全满足自己的需求
- 子类可以重写父类方法
-
案例
- 旧手机功能只是打电话,发短信
- 新手机功能要打电话下支持视频通话,发短信下支持发语音和图片
-
@Override重写注释
- 放在重写后的方法上,校验是否正确重写方法
- 加该注释如果重写错误,编译阶段会有错误提示
- 建议都加上注解,安全优雅
-
注意
- 重写方法的名称,形参列表必须与重写方法的名称和参数列表一致
- 私有方法不能被重写
- 子类重写方法时,访问权限必须大于等于父类(缺省
- 子类不能重写父类静态方法,如果重写会报错
-
-
-
多态
-
定义
- 同类型的对象,执行同一个行为,会表现出不同的行为特征
-
常见形式
- 父类类型 对象名称=new 子类构造器;
- 接口 对象名称=new 实现类构造器;
-
访问特点
-
方法调用
- 编译看左,运行看右
-
变量调用
- 编译看左,运行也看左(多态侧重行为多态)
-
-
前提
- 有继承/实现关系;父类引用指向子类对象;有方法重写
-
类型转换
-
自动转换类型
-
从子到父
- 子类对象赋值给父类类型的变量指向
-
-
强制类型转换
-
从父到子
-
此时必须进行强制类型转换
- 子类 对象变量=(子类)父类类型的变量
-
作用
- 可以解决多态下的劣势,可以实现调用子类独有功能
-
注意
-
如果转型后的类型和对象真实类型不是同一种类型,那么在转换时就会出现类型转换异常ClassCastException
- Animal t =new Tortoise();
- Dog d=(Dog)t;//出现异常ClassCastException
-
-
Java建议强制类型转换前用instanceof判断当前对象的真实类型,再进行强转
-
变量名 instanceof 真实类型
-
判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之
- if(a instanceof Tortoise{Tortoise t =(Tortoise)a;t.layEggs();}else if(a instanceof Dog){DOg d1=(Dog) a; d1.lookDoor();})
-
-
-
-
-
优势
-
在多态形势下,右边对象可以解耦合,便于扩展和维护
- Animal a=new Dog();
- a.run()//后续业务行为随对象而变,后续代码无需修改
-
定义方法时使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利
-
-
劣势
- 多态下不能使用子类的独有方法
-
-
内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)
- public class People{public class Heart{}}
-
使用场景,作用
- 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计
- 内部类通常可以方便访问外部类成员,包括私有成员
- 内部类提供了更好的封装性,内部类本身就可以用private protected等修饰,封装性可以做更多控制
-
静态内部类
-
有static修饰,属于外部类本身
-
他的特点和使用与普通类完全一样的,类有的成分它都有,只是位置在别人里面而已
- public class Outer{//静态成员内部类public static class Inner{}}
-
静态内部类创建对象格式
-
外部类名.内部类名 对象名=new 外部类名.内部类构造器;
- Outer.inner in=new Outer.Inner();
-
-
访问扩展
- 静态内部类可以直接访问外部类的静态成员,外部类的静态成员只有一份可以被共享访问
- 静态内部类中不可以直接访问外部类的实例成员,外部类的实例成员必须用外部类对象访问
-
使用场景
- 如果一个类包含了一个完整的成分,如汽车类中的发动机类
- 特点,使用场景与普通类一样的,类的成分他都有,只是位置在别人里面而已
- 可以直接访问外部类的静态成员,不能直接访问外部类的实例成员
- 开发实际中用的比较少
-
-
成员内部类
-
无static修饰,属于外部类的对象
-
jdk16之前,成员内部类中不能定义静态成员,jdk16开始也可以定义静态成员了
- public class Outer{//成员内部类public class Inner{}}
-
成员内部类创建对象格式
-
外部类.内部类 对象名=new 外部类构造器().new 内部类构造器();
- Outer.Inner in=new Outer().new Inner();
-
-
访问扩展
- 成员内部类中可以直接访问外部类的静态成员,外部类的静态成员只有一份可以被共享访问
- 成员内部类的实例方法中可以直接访问外部类的实例成员,因为必须现有外部类对象才能有内部类对象,所以可以直接访问外部类对象的实例成员
-
-
匿名内部类
-
本质上是一个没有名字的局部内部类,定义在方法中,代码块中等
-
作用
- 方便创建子类对象,最终的目的为了简化代码编写
-
格式
-
new 类|抽象类名|或者接口名(){重写方法;};
- Employee a =new Employee(){public void work(){}};a.work();
-
-
特点
- 匿名内部类是一个没有名字的内部类
- 匿名内部类写出来就会产生一个匿名内部类的对象
- 匿名内部类的对象类型相当于是当前new的那个的类型的子类类型
- 匿名内部类可以作为方法的实际参数进行传输
- 开发中并不是我们主动去定义匿名内部类的,而是别人需要我们写或者我们可以写的时候才会使用,匿名内部类的代码可以实现进一步的简化
-
-
也可以理解成实体类,其对象可以用于在程序中封装数据
-
要求
- 成员变量使用private修饰
- 提供每一个成员变量对应的setXxx()/getXxx()
- 必须提供一个无参构造器
-
区别
-
类中的位置不同
- 成员变量:类中,方法外
- 局部变量:常见于方法中
-
初始化值不同
- 成员变量:有默认初始化值
- 局部变量:没有,使用之前需要完成赋值
-
内存位置不同
- 成员变量:堆内存
- 局部变量:栈内存
-
生命周期不同
- 成员变量:随着对象的创建而存在,随着对象的消失而消失
- 局部变量:随着方法的调用而存在,随着方法的运行结束而消失
-
作用域
- 局部变量:在所归属的大括号中
-
-
成员变量分类和访问
-
静态成员变量(有static修饰,属于类,加载一次可以被共享访问)
- 类名.静态成员变量(推荐)
- 对象.静态成员变量(不推荐)
-
实例成员变量(无static修饰,属于对象,没对象就不加载)
- 对象.实例成员变量
-
什么情况定义
-
静态成员变量
- 表示在线人数等需要被共享访问的信息
-
实例成员变量
- 属于每个对象,且每个对象信息不同时(name,age等)
-
-
-
静态成员方法(有static修饰,属于类和对象共享)
-
类名.静态成员方法
-
对象.静态成员方法(不推荐)
-
注意
- 同一个类中访问静态成员,类名可以不写
- 静态方法只能访问静态的成员,不可以直接访问实例成员
- 静态方法中是不能出现this关键字的
-
-
实例成员方法(无static修饰,属于对象)
-
对象.实例成员方法
-
注意
- 实例方法可以访问静态的成员,也可以访问实例成员
-
-
使用场景
- 表示对象自己的行为的,且方法中需要访问实例成员的,则该方法必须申明成实例方法
- 如果该方法是执行一个通用功能为目的,或者需要方便访问,则可以申明成静态方法
-
对于一些应用程序中多次使用的功能,可以将这些功能封装成静态方法,放在一个类中,这个类就是工具类
-
作用
- 方便调用
- 提高了代码复用
-
注意
- 建议将工具类的构造器私有化,不让工具类对外产生对象(防止有人不知道,调用构造器)
-
为什么不用实例方法做工具类
- 实例方法需要创建对象调用,此时用对象只是为了调用方法,这样会浪费内存
-
是类的5大成分之一(成员变量,构造器,方法,代码块,内部类),定义在类中方法外
-
在Java类下,使用{}括起来的代码被称为代码块
-
分类
-
静态代码块
- 格式:static{}
- 特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次
- 使用场景:在类加载的时候做一些静态数据初始化以便后续使用,使用静态代码块完成数据初始化操作,代码优雅(例如先把54张牌先初始化)
-
构造代码块
- 格式:{}
- 特点:每次创建对象调用构造器执行时都会执行该代码块中的代码,并且在构造器执行前执行
- 使用场景:初始化实例资源
-
-
单例模式
-
可以保证系统中,应用该模式的类永远只有一个实例,即一个类永远只能创建一个对象
-
场景和作用
- 例如任务管理器对象只用一个就行了,可以节省空间
-
饿汉单例模式
-
在类获取对象的时候,对象已经提前创建好了,直接调用就行了不用再new
-
设计步骤
- 定义一个类,把构造器私有
- 定义一个静态变量存储本类对象,初始化对象(可以将静态成员变量私有,防止别人调方法时调错误以为是方法)
- 提供一个返回单例对象的方法,让其他位置可以调用获取一个对象
-
-
懒汉单例设计模式
-
在真正需要该对象的时候,采取创建一个对象(延迟加载对象)
-
设计步骤
- 定义一个类,把构造器私有
- 定义一个静态变量存储一个对象,此时不能初始化对象
- 提供一个返回单例对象的方法,让其他位置可以调用获取一个对象
-
-
区别
- 有没有初始化对象
-
- String字符串类型,可以定义字符串变量指向字符串对象
- String变量每次的修改其实都是产生并指向新的字符串对象
- 原来的字符串对象都是们没有改变的,所以称不可变字符串
-
直接定义:String name =”java";推荐使用
-
通过String类的构造器创建对象
- public String();创建空白字符串对象,不含任何内容
- public String(String original)根据传入的字符串内容,创建字符串对象
- public String(char[] chs)根据字符数组的内容创建字符串对象
- public String (byte[] chs)根据字节数组的内容创建字符串对象
-
面试题
-
两种方式有什么区别
- 以" "方式给出的字符串对象,在字符串常量池中存储(不管出现在哪里见面试题),而且相同内容只会存储一份
- 通过构造器new对象,每次new一次就会创建一个新对象放在堆内存中分开存储
- 证明代码:String s1=“abc”;String s2=“abc”;System.out.println(s1==s2)//true
- char[] chs={‘a’,‘b’,‘c’};String s3=new String(chs);String s4=new String(chs);System.out.println(s3==s4)//false
-
String s2 =new String(“abc”);//此时不仅在字符串常量池中创建字符,也在堆内存中创建字符串对象,但是s2是引用类型存的是数据地址,String s1=“abc”;//这里不在字符串常量池创建字符System.out.println(s1==s2)//false
-
java存在编译优化机制,程序在编译时:“a”+“b”+“c"会直接转成"abc”
-
- public boolean equals (Object anObject)将此字符串与指定对象进行比较,只关心字符内容是否一样
- public boolean equalsIgnoreCase(String anotherString)将此字符串与指定对象进行比较忽略大小写比较字符串,只关心字符内容是否一样
- public int length();返回字符串长度
- public char chaAt(int index);获得某个索引位置的字符
- public char[] toCharArray():将当前字符串转换成字符数组返回
- public String substring(int beginIndex,int endIndex)根据开始和结束索引进行截取,截取到末尾,得到新的字符串(包前不包后)
- public String substring(int beginIndex)从传入的索引截取,截取到末尾,得到新的字符串
- public String replace(CharSequence target,CharSequence replacement)使用新值,将字符串中的就只替换,得到新的字符串
- public String[] split(String regex)根据传入的规则切割字符串,得到字符串数组返回
-
验证码
- 定义可能出现的全部字符
- 循环n次每次随机生成一个索引,提取对应位置的字符连接在一起(charAt方法)
- 好处:代码简单
-
手机号屏蔽
- 键盘录入一个字符串
- 截取字符串前三位,后四位(substring方法)
- 将截取后的两个字符串加上“****”进行拼接,输出结果
-
敏感词替换
- replace方法
-
集合的一种支持索引
-
对象获取
- public ArrayList()创建一个空的集合对象
-
集合添加元素
- public boolean add(E e)将指定元素添加到集合的末尾
- public void add(int index,E element)再次集合中的指定位置插入指定的元素
-
如何创建对象添加元素
- ArrayList list =new ArrayList();
- public boolean add(E e)
- public void add(int index,E element)
-
泛型概念
-
ArrayList就是泛型类,可在编译阶段约束集合对象只能操作某种数据类型
-
ArrayList list=new ArrayList<>();从jdk1.7开始泛型后面的类型声明可以不写
-
集合中只能存储引用类型,不支持基本数据类型
- ArrayList只操作字符串类型
- ArrayList只操作整数类型
-
-
要求:使用泛型,即使集合要接所有数据类型也要写Object
-
常用方法
- public E get(int index)返回指定索引处的元素
- public int size()返回集合中的元素个数
- public E remove(int index)删除指定索引处的元素,返回被删除的元素
- public boolean remove(Object o)删除指定的元素,返回删除是否成功
- public E set(int index,E element)修改指定索引处的元素,返回被修改的元素
-
注意
- 从集合筛选元素并删除,需要从集合后面遍历,可以避免漏掉元素(元素会自动移位置)



