面向对象
本质
以类的方式组织代码 以对象方式的组织(封装)数据
三大特性
封装 继承 多态
封装
高内聚 低耦合
定义:类的内部数据操作细节自己完成,不允许外部干涉;仅暴露少量的方法给外部使用
属性私有(get/set):
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private 数据类型 变量名; //定义私有属性,私有属性不能调用
快捷键:alter+insert可以快捷生成get/set方法
作用:提高程序的安全性,保护数据;隐藏代码的实现细节;统一接口;系统可维护增加
继承
定义:继承是类和类之间的关系 除此之外类和类的关系还有依赖 组合 聚合等
继承关系的两个类 :一个是子类 一个是父类 ,子类继承父类用关键字extends表示
子类与父类:
-
子类和父类之间 从意义上应该具有is a 的关系
-
子类继承了父类 就会拥有父类的全部方法
-
私有的东西无法被继承
-
子类默认调用父类的无参构造
-
调用父类的构造器,必须要在子类构造器的第一行
-
ctrl+h 打开继承树
-
在java中 所有的类都默认继承object类
-
java中只有单继承 没有多继承
-
super.name 调用父类的name
this.name 调用子类的name
super:
- super调用父类的构造方法 必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
super和this区别:
- this调用本身的对象 super代表父类对象的引用
- this没有继承也可以使用 super只能在继承条件下可以使用
- this是本类的构造 super是父类的构造
注意:通过final修饰的类不能继承
多态
定义:同一方法可以根据发送对象的不同而采用多种不同的行为方式
优点:实现动态编译,增强可扩展性
存在条件:有继承关系 子类重写父类的方法,父类引用指向子类对象
一个对象的实际对象是确定的,可以指向的引用类型就不确定,如父类的引用指向子类
Student s1=new Student(); //能调用Student自己的或者继承父类的
Person s2=new Student(); //能指向子类但是不能调用子类独有的方法
注意:
多态是方法多态 属性没有多态
父类和子类有联系 ,若出现异常 ClassCastException为类型转换异常
不能重写的修饰符:static final(常量) private
instanceof 判断对象类型
X instanceof Y 判断X与Y存不存在父子关系,存在则编译通过,X是Y的子类则返回True
构造器
定义: 一个类即使什么都不写 也会自己产生一个方法
要求:和类名相同 没有返回值
作用:使用new关键字必须要有构造器 ;初始化值
一旦定义了有参构造 使用无参就必须显式定义
注意:
1. alter+insert可以快捷生成构造器
2. this. 属性 = 值 ; //表示调用这个类的属性,等号后面是参数传进来的值
3. 一个项目只存在一个main方法
4. 类实例化后会返回一个自己的对象
方法的重写
条件:需要有继承关系 子类重写父类的方法
要求:方法名必须相同 参数列表必须相同 修饰符范围可以扩大但不能缩小
修饰符大小:public>protected>default>private
抛出的异常范围可以被缩小不能被扩大 classnotfoundexception–>exception(大)
目的:父类的功能子类不一定需要,或者不一定满足
快捷键:alt+insert 选择override
注意:
父类的引用可以指向子类
非静态方法子类可以重写父类的方法
子类重写了父类的方法 则指向那个子类的方法
静态方法中方法的调用只和左边的定义有关,与new后面的类无关
重写时子类的方法和父类必须要一致 方法体不同
类型
类型转换
低转高可以自动转
高转低 : 格式:(类型名)要转的对象
注意:父类转子类可能会丢失自己的一些方法
Static
定义:静态导入包
目的: import static java.lang.Math.random; 就可以直接random()调用,不用写Math.random()
格式:
-
静态代码块 直接在类里面写
static{
//静态代码块
} -
匿名代码块 直接在类里面
{
//匿名代码块
}
后台加载顺序:
静态代码块(只执行一次)—>匿名代码块—>构造器
抽象类
定义:abstract修饰的类
abstract修饰方法 是一个抽象方法 只有方法名字 没有方法的实现
一旦有抽象方法 则这个类一定是抽象类
抽象类中可以写普通的方法
不能new这个抽象类 只能靠子类去实现
内部类
定义:内部类就是在一个类的内部再定义一个类
目的:内部类可以获得外部类的私有属性
用法:通过外部类实例化内部类
格式:
Outer outer=new Outer();
Outer.Inner inner=outer.new.Inner();
局部内部类:写在方法里的类
注意:一个java类中可以有多个class类 但是只能有一个publc类
String类
String表示字符串类型 属于引用数据类型 不属于基本数据类型 直接存储在字符串常量池当中
new 对象 是在堆里面开辟内存空间
String s1=“as” 保存的是地址不是as
String已经重写了toString方法 输出字符串对象时输出的不是对象的内存地址而是字符串本身
字符串之间的比较
用==不保险 要用equals方法
x.equals(y) 比较x和y
“asd”.equals(k); 这样也可以用 因为字符串是对象
k.equals(“asd”); 不建议这样用 避免空指针异常
常用的构造方法
String(bytes,数组元素下标的起始位置,长度) 传数组
常用方法:
- char c =“中国”.charAt(1); //取字符串中下标为1的字符
- compareTo 按字典顺序比较两个字符串 返回0则相等 返回-1则前小后大 返回1则前大后小
拿着字符串第一个字母和后面字符串第一个字母比较 能分出胜负就不比了 - contains 判断前面的字符串是否包含后面的字符串 返回布尔型
- endsWith 判断当前字符串是否以某个字符结尾
- equalsIgnoreCase 判断两个字符串是否相等 忽略大小写
- indexOf 判断某个子字符串在当前字符串中第一次出现处的索引
- 判断数组长度和判断字符串长度不一样 判断数组长度是length属性 判断字符串长度是length()方法
- “sadadead”.replace(target,replacement); 将字符串里的target替换成replacement
- split("-"); 将字符串以-进行拆分
- substring(起始下标,结束下标); 截取字符串 前闭后开
- trim() 去除字符串前后空白
- String中只有一个方法是静态的 valueof 将非字符串转为字符串,底层用的是tostring()方法
当参数是对象时,若没有重写toString方法,则返回对象的内存地址
String.valueOf(k); Integer转字符串
StringBuffer类
目的:java中的字符串是不可变的 所以拼接时会产生新字符串 占用大量空间
定义:底层是一个数组 初始容量是16字节
格式:
StringBuffer s1=new StringBuffer();
s1.append(“a”); 追加
append方法底层在进行追加时,如果满了会自动扩容
注意:
-
为什么StringBuffer类可以更改
StringBuffer底层字符串没有被final修饰 而String底层被final修饰了 所以StringBuffer可以
-
StringBuffer优化
在创建StringBuffer是最好初始化一个容量,减少扩容次数
例如:StringBuffer s2=new StringBuffer(100); 创建初始容量为100的数组
StringBuilder:
StringBuffer中的方法都有synchronized关键字修饰 表示StringBuffer在多线程环境下运行是安全的
StringBuilder没有synchronized关键字修饰 表示StringBuilder在多线程环境下运行是不安全的
包装类
java中对8中基本数据类型对应准备了8中包装类型,属于引用数据类型,父类是object
目的:
因为有时方法无法接收基本数据类型,所以可以把数据类型包装成一个包装类,再new出对象,这样传进去的就是对象了
8种包装类:
byte java.lang.Byte(父类Number)
short java.lang.Short(父类Number)
int java.lang.Integer(父类Number)
long java.lang.Long(父类Number)
float java.lang.Float(父类Number)
double java.lang.Double(父类Number)
boolean java.lang.Boolean(父类Object)
char java.lang.Character(父类Object)
Number是一个抽象类 无法实例化对象
装箱与拆箱:
基本数据类型转换为引用数据类型(装箱)
Integer i =new Integer(123);
引用数据类型转换为基本数据类型(拆箱)
int retvalue=i.intValue();
自动拆箱和自动装箱:
自动装箱 Integer x=100; int自动转为对象 x保存的是对象的内存地址
自动拆箱 int y=x; 对象自动转为int
注意:
==不会触发自动拆箱机制 只有±*/会触发自动拆箱机制
==永远只判断两个对象的内存地址是否相等
不是数字不能包装成Integer
java中为了提高程序执行效率 将-128到127之间所有的包装对象提前创建好 放到了一个方法区的整数型常量池中,目的是只要用这个区间的数据不需要new 直接从整数型常量池当中取出来
转自狂神说java
Integer方法:
int a = Integer.parseInt(string); //返回int值,字符串转int,"123"--->123
static Integer valueOf(String s); // 静态方法 字符串转Integer
Intger s = Integer.valueOf("100");
Double.parseDouble(); // 字符串转double
Float.parseFloat(); //字符串转float
转自狂神说java
Date类
定义:SimpleDateFormate是java.text包下 日期格式化
方法:
Date nowTime = new Date(); 获取当前时间 输出一个日期字符串
日期转成字符串:
SimpleDateFormate s = new SimpleDateFormate(“yyyy-MM-dd”); 日期格式化
在日期格式中 -这类符号可以随意写 yyyy/MM/dd
String d = s.format(nowTime); 返回的d就是当前格式下的时间,日期转成字符串
字符串格式转成日期:
String time = “2021-09-28”;
SimpleDateFormate s = new SimpleDateFormate(“yyyy-MM-dd”);
Date x = s.parse(time); 把字符串格式转成日期
获取自1970年1月1日00:00:00 000到当前系统时间的总毫秒数:
long now = System.currentTimeMillis();
Date time = new Date(1); 参数是一个毫秒,返回自1970年1月1日00:00:00 000起始的时间,参数是过了多少毫秒
获取一个方法运行时长:
long begin = System.currentTimeMillis();
调用方法
long end = System.currentTimeMillis();
end-begin
System类
System.out(); out是System类的静态变量
System.out.println(); println()方法不是System类的,是PrintStream类的方法
System.gc() 建议启动垃圾回收器
System.currentTimeMillis(); 获取自1970年1月1日00:00:00 000到当前系统时间的总毫秒数:
System.exit(0) 退出JVM
枚举类型
枚举也是引用数据类型,
编译之后也是生成class文件,
枚举中的每一个值可以看作是常量
格式:
enum 枚举类型名{
枚举值1,枚举值2
}
注意:
switch支持枚举
数字类
包:
java.text.DecimalFormat
符号表示:
#任意数字
,千分位
. 小数点
0 不够补0
格式:
DecimalFormat df = new DecimalFormat(数字格式);
BigDecimal 属于大数据 精度极高 不属于基本数据类型 属于java对象,需要调用方法求和
随机数:
Random r = new Random();
int num = r.nextInt(101); 随机产生一个int类型取值范围0-100的数字
接口
本质:契约
关键字:interface
定义的属性:常量
实现接口的类声明规范:public class 类名(接口名+impl) implements 接口名(可以有多个接口);
注意:
- 接口中的所有定义都是抽象的 Public abstract
- 接口需要实现类
- 实现接口的类 必须重写接口中方法
作用:约束 ,定义方法让不同的人实现 接口不能被实例化
异常
定义:
java把一切当作对象来处理 ,并定义一个基类java.lang.Throwable作为所有异常的超类
在java API中已经定义了许多异常类 ,这些异常类分为错误ERROR和异常Exception
Error与编写者无关 , 由java虚拟机生成并抛出 这些错误不可查
Exception分为运行时异常和非运行时异常
格式:
try{
//try监控区域
}catch(异常类型){
//出现错误时执行的代码
}finally{
//无论是否出错都会执行的代码
}
e.printStackTrace(); 打印异常
注意:
finally可以不用
catch可以写多个 但是最大的异常要写在最后面
异常类型 Error和Exception小于Throwable
方法中抛出异常 throw
方法上抛出异常 throws
快捷键:
ctrl+alt+T 可以把包裹的代码自动加入异常捕获
alt+enter 自动处理异常
自定义异常:
继承Exception类
public class 自定义异常名 extends Exception{
public 自定义异常名(){
}
public 自定义异常名(String s){
super(s);
}
}
经验总结:
处理运行时异常时 采用逻辑区合理规避同时辅助Try-catch处理
在多重catch块后面 可以加一个catch(Exception)来处理可能会被遗漏的异常
对于不确定的代码也可以加上Try-catch处理潜在的异常
尽量去处理异常 不要只是简单调用printStackTrace()去打印输出
具体如何处理异常 要根据不同业务需求和异常类型去决定
尽量添加finally语句块去释放占用的资源
经典异常:
空指针异常NullPointerException
类型转换异常ClassCastException
数组下标越界异常ArrayIndexOutOfBoundsException
数字格式化异常NumberFormatException