Java基础
1、三大特性
封装
理解:私有化类成员变量,提供对外访问的接口
特点:
1、类中成员变量设为私有,只暴露出公开的访问接口,增强了类的安全性,避免外界随意修改
2、解耦合,能够更加关注细节,而不去改变接口本身
缺点:
1、容易被打破,例如继承
Example:
/**
* @author wys
* @date 2021/1/12 5:27 下午
*/
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
继承
理解:子类继承父类
特点:
1、子类通过extends关键字继承父类
2、通过继承,实现类的复用,避免了大量重复代码
缺点:
1、继承破坏了封装性,子类如果太依赖父类,会造成耦合
Example:
/**
* @author wys
* @date 2021/1/12 5:46 下午
* 比如我们的手机就可以分为不同的牌子,但是每种牌子都要有名称和价格
* 这样就可以抽象出来一个通用的手机来定义名称和价格
*/
public class Phone {
private String name;
private BigDecimal price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
@Override
public String toString() {
return "name:"+this.getName()+"price:"+this.getPrice();
}
}
public class MiPhone extends Phone{
public void desc() {
System.out.println("这是小米手机");
}
}
public class IPhone extends Phone{
public void desc() {
System.out.println("这是苹果手机");
}
}
/**
* @author wys
* @date 2021/1/12 5:50 下午
*/
public class Main {
public static void main(String[] args) {
MiPhone mi = new MiPhone();
mi.setName("小米手机");
mi.setPrice(new BigDecimal("2000"));
System.out.println(mi.toString());
IPhone iPhone = new IPhone();
iPhone.setName("苹果手机");
iPhone.setPrice(new BigDecimal("8000"));
System.out.println(iPhone.toString());
}
}
继承的规则:
- 单继承:一个类只能继承一个父类
- 多重继承:一个类可以有多个层级关系,比如B继承A,C继承B
多态
理解:一个事物的多种形态,同一个接口的不同实例对象
前置要求:继承,重写,父类引用指向子类
优点:
1、提高了代码的拓展性
2、解除类型之间的耦合关系
缺点:
1、父类不能使用子类特有的功能
Example:
/**
* @author wys
* @date 2021/1/13 10:29 上午
*/
public interface Phone {
void desc();
}
public class IPhone implements Phone{
@Override
public void desc() {
System.out.println("苹果手机");
}
}
public class MiPhone implements Phone{
@Override
public void desc() {
System.out.println("小米手机");
}
}
关键字
this:
this指代当前类的对象,例如子类继承父类,重写了父类的方法,可以用this关键字调用子类方法
super:
super指代父类对象,可以调用父类方法
final:
修饰位置:
- 类:类不能被继承
- 方法:不能被重写
- 变量:不能被改变
- 修饰引用类型:引用类型的内存地址不可变,指向的值可以变。
final 修饰的变量 会直接放在变量池中,如果一个类调用final修饰的变量是不会加载类的
抽象类和接口的区别:
- 抽象,使用extends关键字继承抽象类,子类使用,使用implements关键字实现接口
- 抽象类可以有抽象方法和非抽象方法,接口只能有抽象方法,但是jdk1.8之后接口有个default关键字,可以编写方法体
- 一个类只能继承一个抽象类,一个类可以 实现多个接口
- 接口和抽象类都不能被实例化
类实例初始化过程:
- 父类静态属性
- 父类静态代码块
- 子类静态属性
- 子类静态代码块
- 父类普通代码块
- 父类普通成员变量
- 父类构造方法
- 子类普通代码块
- 子类普通成员变量
- 子类构造方法
2、异常
异常是整个Java必不可少的一种情况,在整个异常体系中,有一部分我们是需要手动处理的,是需要捕获,或者抛给外层处理,或是一些不可预料,例如空指针,不过目前Idea发展已经很快了,很多我们发现不了的异常,Idea都可以提示我们,最常见的可以看下面这个
异常体系分为下面这个图架构:
分为Exception 和 Error
Exception
异常,异常又分为编译时异常和运行时异常
编译时异常
这种异常在编译时就会报异常,例如下图,需要我们手动处理的:
运行时异常
这种异常编译时不会报错,但是在使用时,如果数据不符合要求就会报错,例如空指针异常,类转换异常等等
空指针异常示例:
类转换异常示例:
Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader 'bootstrap')
at org.wys.demo.jvm.util.ArrayUtil.main(ArrayUtil.java:17)
可见这种异常我们虽然没办法在编译时发现这些错误,但是我们在编写代码的时候可以针对这些异常进行处理,其次就是我们定义泛型或者类型的时候,尽量明确类型信息,这样如果错误使用了对应的类型,就会出现异常
Error 错误
除了异常,其次就是错误了,经常见的就是栈溢出和OOM,栈溢出出现情况最多的就是方法栈调用太深,导致发生这个问题,同样也是不可预见的
栈溢出示例
(OOM)堆内存溢出实例:
这些我们也是不可预见的,同时遇到这种错误,也不好捕获,最简单方式就是重启项目,清空内存,但是假如数据库记录行过多,导致一次性load进内存,也会出现OOM,这就要考虑到分段读写处理问题,这里不过多叙述
自定义异常
除了上面Jdk提供的最基础异常之外,我们还可以自定义属于自己的异常信息,例如我们可以继承Throwable类或者是Exception,实现自己的异常信息,然后通过捕获不同类型的异常,去处理不同的业务
public class ArrayUtil {
public static void main(String[] args) {
byte[] bytes = new byte[1];
try {
test();
} catch (MyException e) {
System.out.println("my exception");;
} catch (IOException e) {
System.out.println("io exception");
}
System.out.println(bytes.length);
}
public static void test()throws MyException,IOException {
// throw new MyException("my exception");
throw new IOException("io exception");
}
static class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
}
通过改变异常类型,就能处理不同的异常业务,这也是我们最常用的一种处理异常的方式,但是上面都是简单介绍了一些异常的类型,真正使用异常的话,需要注意多种方面,例如异常对项目的影响,以及异常信息的处理,异常编码展示,以及全局异常,AOP处理异常等等,总之,需要在不同的业务场景处理不同的异常。