文章目录
static
1 修饰成员变量
使用方式:
public class Static {
private static String name="Bob";
public static void main(String[] args) {
System.out.println(Static.name);
}
}
应用场景:
public class Constants{
public static final String VERSION="1.0";
}
2修饰成员方法
使用方法:
public class Static {
public static void show(){
System.out.println("hello");
}
public static void main(String[] args) {
Static.show();
}
}
应用场景:
工具类:
public class StringUtils {
public static boolean isNotEmpty(String value){
return value!=null && !"".equals(value);
}
}
3 静态代码块/非静态代码块/构造函数
- 静态代码块:对象创建的时候执行,只执行一次
- 非静态代码块:对象创建的时候执行,每次创建对象执行一次
- 构造函数:对象创建的时候执行,每次创建执行一次,在非静态代码块执行之后执行。
public class Static {
static{
System.out.println("Static静态代码块执行了1");
}
{
System.out.println("Static非静态代码块执行了3");
}
public Static(){
System.out.println("Static构造函数执行了4");
}
}
public class SonStatic extends MyStatic{
static{
System.out.println("SonStatic静态代码块执行了2");
}
{
System.out.println("SonStatic非静态代码块执行了5");
}
public SonStatic(){
System.out.println("SonStatic构造函数执行了6");
}
}
4 静态代码块 非静态代码块 构造函数的执行顺序
父类静态代码块 子类静态代码块 父类非静态代码块 父类构造函数 子类非静态代码块 子类构造函数
设计模式[单例模式]
1 饿汉式
步骤:
- 将类的构造器私有
- 定义一个类变量记住类的一个对象
- 定义一个类方法发返回对象
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
}
2 懒汉式
步骤
- 将类的构造器私有
- 定义一个类变量存储对象
- 提供一个类方法判断对象是否为null 如果为null 创建 否则返回
public class Singleton {
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
懒汉式和饿汉式构造单例的优缺点:
从时间和空间分析:
饿汉式 以空间换时间创建对象的速度快 但是可能会造成资源的浪费
懒汉式 以时间换空间 创建对象速度慢于饿汉式 可能节省空间
从安全分析
饿汉式: 没有线程安全问题
懒汉式 :存在线程安全问题,可能会创建多个实例
如何解决线程安全问题:
加锁【sychroinzed】
public class Singleton {
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
synchronized (Singleton.class){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
}
此方案所有的线程获取实例的时候不管实例有没有都需要先竞争锁才能获取实例性能会受到影响
解决:
public class Singleton {
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
return instance;
}
}
方法的重写和重载
继承( extends)
public class A{
}
pubilc class B extends A{
}
方法修饰符
public protected 缺省 default private
1 重写:父类和子类之间的一种多态的表现
子类中的方法方法名方法参数和方法返回值和父方法的一致性
子类中的方法 修饰符 要大于等于父类方法的修饰符
子类的方法 抛出的异常要小于等于父类方法抛出的异常
架子:
修饰符 返回值 方法名(参数) throws 异常类型{}
2 重载:一个类中的多态的表现
方法名相同参数不同
重写和重载的区别:
相同点:
他们都是多态的一种表现
不同点
重写:父类和子类的多态表现
重载一个类中的多态的表现
重写:返回值 方法名 参数必须一致 修饰符大于等于父类的方法 排除的异常小于等于父类方法抛出的异常
重载:方法 名相同 参数不同
final的使用
1 修饰类
这个类不能被继承
2 修饰方法
方法不能被重写
3 修饰变量
修饰简单的数据类型 变量必须被赋值 后期不能修改
修饰引用数据类型 变量必须被赋值 后期引用数据类型的地址值不能被修改 但是引用对象中的属性可以修改
final关键字的作用
它可以修饰类 方法和变量 修饰类 类不能被继承 修饰方法方法不能被重写 修饰变量 如果变量是简单数据类型值不能被修改 如果修饰引用数据类型引用地址值不能 被修改 但是引用对象中的属性值是可以被修改的
抽象类和接口
1抽象类(abstract)
public abstract class Abstract{
private String name;
public final static String VERSION="2.0";
public void show(){
system.out.println("hello");
public abstract void add();
public static void main(String []args){
system.out.println(111);
}
}
2 接口(interface)
public interface Interface{
String name="Bob";
pubilc void show();
//默认方法 jdk1.8之后
default void say(){
system.out.println("111");
}
//静态方法
static void add(){
system.out.println("abc");
}
pubilc static void main(String[] args){
system.out.println("lalala");
}
}
抽象类和接口的区别
- 抽象类的关键字是abstract 接口关键字interface;
- 抽象类被类继承extends 接口被类实现 implements
- 抽象类只能被单继承 接口可以被多实现
- 抽象类汇总可以声明普通变量常量普通方法抽象方法main 接口只能声明常量、抽象方法、在1.8接口中添加了两类方法一个是default方法一类是static静态方法 main 方法
匿名内部类
1 如何实现匿名内部类
pubilc class A{
public static void main(String[] args ){
Interface ins = new MyInterface() {
@Override
public void eat() {
System.out.println("饿了吗");
}
};
ins.eat();
}
}
应用的场景
Thread //线程的业务操作
Thread t = new Thread(new Runnable(){
public void run(){
}
});
枚举类
1如何定义枚举类
性别: 男 女 未知
MYSQL: 1 0 2
public enum GenderEnum {
MAN(1,"男"),WOMAN(0,"女"),OTHER(2,"未知");
private String desc;
private Integer code;
GenderEnum(Integer code,String desc){
this.desc = desc;
this.code = code;
}
public Integer getCode(){
return code;
}
public String getDesc(){
return desc;
}
}
应用的场景
定义错误信息描述的时候
HTTP状态码[HttpStatus]
泛型
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult<T> {
private Integer code;
private String msg;
private Long total;
private List<T> list;
}
public class App {
public static void main(String[] args) {
List<User> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
list.add(user);
}
PageResult<User> pageResult = new PageResult<>(200,"查询成功",100L,list);
List<User> userList = pageResult.getList();
for (User user : userList) {
}
}
}
2 泛型接口
public interface MyBaseMapper<T> {
//新增
public int save(T t);
}
BaseMapper
3 泛型方法
public <T> T save(T t){
return t;
}
4 通配符泛型
/**
* extends:继承 上限
*/
List<? extends User> list = new ArrayList<>();
/**
* super:父 下限
*/
List<? super User> list2 = new ArrayList<>();
Obhect常用的API
1 toSting
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", gender=" + gender +
'}';
}
@Data:
@ToString注解
2 equals
String name="BOb";
String username="BOb";
if(name.equals(username)){
}
==和equals的区别
==
如果是基本的数据类型比较的是值
如果是引用的数据类型比价偶读是地址值
equals Object自带的equals内部使用的是==
Integer i = 100;
Integer j = 100;
i==j true
Integer i = 200;
Integer j = 200;
i==j false
Integter有一个缓存数组把-128~127的所有数值创建成Integer对象 把对象提前放到数组中
i=100和j=100都是从数组中获取Integer对象,因为获取的是同一个,所以==返回true
i=200和j=200因为数组中不存在 需要创建对象 创建了两次所以是两个对象所以返回false
hashcode值相等 equals是否也相同
hashcode相同 equals不一定相同
重写equals需要重写hashcode吗
需要
当hashMap中存入数据先计算key的hash的值然后对数组的长度取余判断存储在数组的位置然后使用equals对该位置上是否已经存在相同的数据 如果是替换不是的话存入数组下面的链表中 如果重写了equals方法没有重写hashcode方法就可能导致Map中存储了相同equals两个数据在map中
public class User {
private Long id;
private String name;
public User() {
}
public User(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object user) {
if(user instanceof User){
User u = (User) user;
if(this.name.equals(u.getName())){
return true;
}
}
return false;
}
}
public class App {
public static void main(String[] args) {
User user1 = new User(1L,"TOM");
User user2 = new User(2L,"TOM");
System.out.println(user1.equals(user2));
System.out.println(user1.hashCode()%16);
System.out.println(user2.hashCode()%16);
Map<User,Object> map = new HashMap<>();
map.put(user1,"123");
map.put(user2,"456");
}
}
Map map = new HashMap();
map.put(key1,value1);
map.pupt(key2,value2);
如果key1和key2是相同的,那么map中应该只有一个值是 value2。
如果我们只是重写了equals,没有重写hashcode,就会导致 key1和key2相同,但是计算出的hash值不相同,最总会导致map中存了两个一模一样的key在集合中。
4 clone
深克隆和浅克隆
public static void main(String[] args) {
User user = new User(1L,"TOM",1,null);
//浅克隆
// User user2 = user;
//
// System.out.println(user.getName());
// user2.setName("JERRY");
// System.out.println(user.getName());
//深克隆
String json = JSON.toJSONString(user);
User user3 = JSON.parseObject(json, User.class);
System.out.println(user);
System.out.println(user3);
System.out.println(user.getName());
user3.setName("ROSE");
System.out.println(user.getName());
}
包装类与基本数据类型
1java中的基本数据类型
byte short int long
double float
boolean
char
2 对应的包装类
Byte Short Integer Long Double Float Boolean Character
StringBuffer和StringBuilder
String StringBuffer和StringBuilder的区别
String是final修饰的,值不能被修改,要想修改,创建一个新的对象赋值给对应的变量,这种操作方式性能比较低
StringBuilder是线程不安全的, 性能高
StringBuffer线程安全的,性能低,之所以是线程安全,是因为所有的数据操作方法上都有一个Sychronized锁
Math
1 Math.round()
四舍五入
Math.round(11.5) 与 Math.round(-11.5)分别返回的值为?
12 和 -11
2Math.random()
获取一个随机数 范围[0.0,1.0)
3Math.ceil()
向上取整
11.1 12
应用场景:计算总页数
(4)Math.min()/Math.max()
取最小值/取最大值
BigDecimal
应用场景
和钱有关的项目中用
-
-
- /
-
public class App {
public static void main(String[] args) {
System.out.println(0.2+0.1);
BigDecimal a = new BigDecimal("0.2");
BigDecimal b = new BigDecimal("0.1");
System.out.println(a.add(b));
System.out.println(a.subtract(b));
System.out.println(a.multiply(b));
System.out.println(a.divide(b));
}
}
日期和时间
(1)Date
Date date = new Date();
(2)Calander
1.获取Calander
Calander instance = Calander.getInstance();
2.获取时间
instance.getTime();
3.获取年月日
instance.get(Calander.XXX);
4.计算前几天日期
instance.add(Calander.XXX, value);
5.设置日期
instance.set(Calander.XXX,value);
(3)LocalDate,LocalTime,LocalDateTime
LocalDateTime now = LocalDateTime.now();
now.getYear()
4 格式化
> SimpleDateFormat
多线程的环境下存在线程安全问题
DateTimeFormatter
public class App {
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
String format = formatter.format(LocalDateTime.now());
System.out.println(format);
String rst = LocalDateTime.now().format(formatter);
System.out.println(rst);
}
}**
Arrays
(1)数组转集合
List list = Arrays.asList(arr);
(2)集合转数组
String[] arrs = list.toArray(new String[0]);
(3)排序
Arrays.sort(arr, new Comparator() {
@Override
public int compare(String o1, String o2) {
//o1 排在 o2 的前面 返回 正整数
//o1 排在 o2 的后面 返回 负数
//其他 返回0
return -1;
}
});
如何将集合转换为数组,如果将数组转换成集合?
Arrays.asList/ list.toArray
JSON转换
JSON:
[]:集合/数组
{}:对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
private Integer gender;
private List<Address> addresses;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
private Long id;
private String province;
private String city;
private String area;
private String detail;
}