java基础
这些java基础的相关知识是我准备实习期间总结一些网上java基础和自己被面试官询问到的一些知识点,供大家学习参考,有问题可私信我,后续会更新集合、spring、线程、mysql、redis等相关知识点和面试易考点~~
向上转型
向上转型:一句话总结就是“父类引用指向子类对象”
关于方法:父类引用可以调用子类和父类公用的方法(如果子类重写了父类的方法,则调用子类的方法),但子类特有的方法无法调用。
关于属性: 父类引用可以调用父类的属性,不可以调用子类的属性
向上转型的作用
- 减少一些重复性的代码
- 对象实例化的时候可以根据不同需求实例化不同的对象
自增(前)b= a可以写成a=a 1,b=a。 自增(后)b=a 可以写成b=a,a=a 1。
抽象类
- 使用abstract修饰的类或方法,就抽象类或者抽象方法
- 抽象类是不能具体的描述一个对象,不能用抽象类直接实例化对象
- 抽象类里面的成员变量和成员方法,都是和普通类一样的,只不过就是不能进行实例化了
- 当一个普通类继承这个抽象类后,那么这个普通类必须重写抽象类当中的所有的抽象方法(我们之前说过抽象类是不具体的,没有包含足够的信息来描述一个对象,所以我们需要把他补充完整)
- 但当一个抽象类A继承了抽象类B,这是抽象类A就可以不重写抽象类B当中的抽象方法
- final不能修饰抽象类和抽象方法(因为抽象类存在的最大意义就是被继承,而被final修饰的不能被继承,final和抽象,他们两个是天敌)
- 抽象方法不能被private修饰(抽象方法一般都是要被重写的,你被private修饰了,还怎么重写)
- 抽象类当中不一定有抽象方法,但如果一个类中有抽象方法,那么这个类一定是抽象类。
接口
- 接口中可以包含变量和方法,变量被隐式指定为 public static final,方法被隐式指定为 public abstract(JDK 1.8一个类可以同时实现多个接口,一个类实现某个接口则必须实现该接口中的抽象方法,否则该类必须被定义为抽象类
- 接口支持多继承,即一个接口可以继承(extends)多个接口,间接解决了 Java 中类不能多继承的问题。
抽象类和接口有什么区别
继承方面
抽象类只能单继承;而接口可以多继承
成员属性方面
抽象类中可以有普通属性,也可以有常量;
接口中的成员变量全部默认是常量,使用public static final修饰,这个可以省略不写
代码块方面
抽象类可以含初始化块;
接口不能含初始化块
构造函数方面
抽象类可以有构函数,但是这里的构造函数不是用来创建对象的,而且用来被实现类调用进行初始化操作的
接口不能有构造函数;
方法方面
接口在JDK1.8之后可以定义抽象方法(无方法体)、default修饰的默认方法(有方法体)、static修饰的静态方法(有方法体),JDK1.8以前是只能有抽象方法。
抽象类中除了静态方法和抽象方法外还可以有普通方法。
二者相同之处
接口与抽象类都不能被实例化,需要被其他进行实现或继承。
接口与抽象类里面都能包含抽象方法,实现接口或继承抽象类的子类都必须实现这些抽象方法。
设计模式
1.JDK中常用的设计模式
单例模式:用于 Runtime,Calendar 和其他的一些类中。
工厂模式:被用于各种不可变的类如 Boolean,像 Boolean.valueOf。
观察者模式:被用于 Swing 和很多的事件监听中。
装饰器模式:被用于多个 Java IO 类中。
2.Spring中常用的设计模式
工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
单例模式:Bean默认为单例模式。
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
3. 单例模式
某个类只能生成一个实例,该实例全局访问,例如Spring容器里一级缓存里的单例池。
优点:
唯一访问:如生成唯一序列化的场景、或者spring默认的bean类型。
提高性能:频繁实例化创建销毁或者耗时耗资源的场景,如连接池、线程池。
缺点:
不适合有状态且需变更的
实现方式:
饿汉式:线程安全速度快,饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。
懒汉式:双重检测锁,第一次减少锁的开销、第二次防止重复、volatile防止重排序导致实例化未完成,而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。本身是非线程安全的
静态内部类:线程安全利用率高
枚举:effictiveJAVA推荐,反射也无法破坏
4. 工厂模式
定义一个用于创建产品的接口,由子类决定生产何种产品。
优点: 解耦:提供参数即可获取产品,通过配置文件可以不修改代码增加具体产品。
缺点: 每增加一个产品就得新增一个产品类
5. 抽象工厂模式
提供一个接口,用于创建相关或者依赖对象的家族,并由此进行约束。
优点: 可以在类的内部对产品族进行约束
缺点:假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。
6.观察者模式
观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象(目标对象)的状态发生改变时,所有依赖于它的对象(观察对象)都得到通知并被自动更新。
特点:被观察者和观察者一般是一对多的关系,一个被观察者对应多个观察者,当一个被观察者的状态发生改变时,被观察者通知观察者,然后可以在观察者内部进行业务逻辑的处理。
7.装饰器模式
装饰器模式是一种结构型设计模式,用于在不修改原有对象的基础上动态地给对象添加新的功能。装饰器模式通过创建一个新的装饰器类,继承原有类的基本功能,然后扩展或覆盖原有功能。装饰器模式可以在运行时根据需要灵活地给对象添加或组合功能。
8.代理模式
给一个对象提供一种代理对象以控制对该对象的访问。 简单点理解: 目标对象:原对象,我们需要通过代理对象控制它的访问,扩展其功能。 代理对象:代理模式产生的对象,是原对象的替身,在原有基础上进行修改。 在不改变原对象代码的基础上对原对象的功能进行扩展 再简单点理解: 比如点外卖事件 你想吃麻辣烫,自己又不想去店里吃,所以你点外卖,此时的外卖小哥,可以看作为代理对象。而你又想在吃完麻辣烫后喝一杯珍珠奶茶,所以你又联系外卖小哥帮你去店里买一杯。这个过程可以理解为加的扩展功能。
什么是面向对象
Java是面向对象的编程语言,不同于C语言是面向过程的。对于面向对象和面向过程的区别,举一个简单的例子说明一下(我们以洗衣机洗衣服为例)∶
面向过程:
面向过程的编程方式,程序会将要完成的某一个任务拆解成一系列的小步骤(函数),如:。
①打开洗衣机:methodo1()
②放入要洗的衣服:method02()。
③放入洗衣粉:method03()。
④清洗: methodo4()
⑤烘干: method05()
面向对象:面向对象的编程方式,程序会将要完成的洗衣机洗衣服的任务拆分成如下两个对象:
人(Person ):Person在洗衣机洗衣服这个程序任务中有三个作用,分别是打开洗衣机、放入要洗的衣服、放入洗衣粉
洗衣机(Nachine ): Machine在洗衣机洗衣服这个程序任务中有两个作用,分别是清洗、烘干
Java对象创建的方式
- 使用new关键字创建对象
- 反射: 通过反射创建对象的方式又有两种,一是通过Class.newInstance
public void aa() throws Exception{
Class c = Student.class;
Student student =(Student)c.newInstance();
student.setSId(1);
system.out.println(student.getSId());
}
二是通过调用构造器再去创建对象Constructor.newInstance
先通过反射获取类中无参构造器,然后通过newInstance()获取对象:
代码语言:javascript复制public void aa() throws Exception{
Class<Student> c = Student.class;
Constructor<Student> constructor = c.getConstructor();
Student student = constructor.newInstance();
student.setSId(1);
System.out.println(student.getSId( ));
}
3. Clone
通过Clone创建对象首先要在实体类中必须先实现Cloneable接口并复写Object的clone方法(因为Object的这个方法是protected的,你若不复写,外部也调用不了呀)。
代码语言:javascript复制@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Cloneable {
private int sId;
private String sName;
@Override
public Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
}
代码语言:javascript复制public void aa() throws CloneNotSupportedException {
student_student = new Student();
Student clone = student.clone();
clone.setSId(1);
System.out.println(clone.getSId());
}
- 反序列化 序列化:指把 Java 对象转换为字节序列的过程; 反序列化:指把字节序列恢复为 Java 对象的过程; 因此我们可以通过反序列化创建对象,具体代码如下:
public void aa() throws IOException,ClassNotFoundException {
File file = new File("E:/a.txt");
FileOutputStream fos = new FileoutputStream(file);
objectoutputStream oos = new objectOutputStream(fos);
Student student1 = new Student();
oos. writeobject(student1);
FileInputStream fis = new FileInputStream(file);
0bjectInputStream ois = new ObjectInputStream(fis);
Student student2 = (Student) ois.readObject();
student2.setSId(1);
System.out.println(student2.getSId());
}
简述面向对象的三个基本特征
继承:继承是Java中面向对象最显著的一个特征,继承是从已有的类中派生出新的类,新的类可以吸收已有的属性、行为,并扩展新的能力。Java中不支持多继承,但是接口可以支持多实现。
封装:将同一类事物的特征和功能包装在一起,只对外暴露需要调用的接口。封装也称为信息的隐藏,在Java中接口是体现封装最常用的方法,在接口中我们没有任何功能的实现(具体实现都交给实现类),只是定义了一系列抽象的方法声明用于外部调用。
多态:封装和继承都是为多态来服务的,多态是指同一个行为具有多个不同的表现形式。在Java中方法的重载和重写是实现多态的2种方式。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载。方法重载体现了编译时的多态性。
重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,重载对返回类型没有特殊的要求。方法重写体现了运行时的多态性。
多态的三要素:继承、重写、父类指向子类引用
Get和Post请求区别
HTTP请求:
方法 | 描述 |
---|---|
GET | 向特定资源发送请求,查询数据,并返回实体 |
POST | 向服务器上传新的内容 |
PUT | 向指定资源提交数据进行处理请求,可能会导致新的资源建立、已有资源修改 |
HEAD | 类似GET请求,返回的响应中没有具体的内容,用于获取报头 |
DELETE | 请求服务器删除指定标识的资源 |
OPTIONS | 可以用来向服务器发送请求来测试服务器的功能性 |
TRACE | 回显服务器收到的请求,用于测试或诊断 |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 |
get和Post区别:
GET | POST | |
---|---|---|
可见性 | 数据在URL中对所有人可见 | 数据不会显示在URL中 |
安全性 | 与post相比,get的安全性较差,因为所 发送的数据是URL的一部分 | 安全,因为参数不会被保存在浏览器 历史或web服务器日志中 |
数据长度 | 受限制,最长2kb | 无限制 |
编码类型 | application/x-www-form-urlencoded | multipart/form-data |
缓存 | 能被缓存 | 不能被缓存 |
HTTP常见响应状态码
100:Continue --- 继续。客户端应继续其请求。
200:OK --- 请求成功。一般用于GET与POST请求。
301:Moved Permanently --- 永久重定向。
302:Found --- 暂时重定向。
400:Bad Request --- 客户端请求的语法错误,服务器无法理解。
403:Forbideen --- 服务器理解请求客户端的请求,但是拒绝执行此请求。
404:Not Found --- 服务器无法根据客户端的请求找到资源(网页)。
500:Internal Server Error --- 服务器内部错误,无法完成请求。
502:Bad Gateway --- 作为网关或者代理服务器尝试执行请求时,从远程服务器接收到了无效的响应。
重定向和转发区别
重定向:redirect:
地址栏发生变化
重定向可以访问其他站点(服务器)的资源
重定向是两次请求。不能使用request对象来共享数据
转发:forward:
转发地址栏路径不变
转发只能访问当前服务器下的资源
转发是一次请求,可以使用request对象共享数据
8种基本数据类型和取值范围
基本类型 | 大小(位/bit) | 字节数(byte) | 最小值 | 最大值 | 默认值 | 包装器类型 |
---|---|---|---|---|---|---|
boolean | - | - | false | true | false | Boolean |
char | 16 bits | 2 bytes | Unicode 0 | Unicode 2^16-1 | 空 | Character |
byte | 8 bits | 1 byte | -2^7 | 2^7-1 | 0 | Byte |
short | 16 bits | 2 bytes | -2^15 | -2^15-1 | 0 | Short |
int | 32 bits | 4 bytes | -2^31 | -2^31-1 | 0 | Integer |
long | 64 bits | 8 bytes | -2^63 | -2^63-1 | 0 | Long |
float | 32 bits | 4 bytes | 0.0 | Float | ||
double | 64 bits | 8 bytes | 0.0 | Double |
static关键字
方便在没有创建对象的情况下来进行调用(方法/变量)
被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。(注意,只要是静态成员,方法,代码块是在类加载过程中就运行的)
static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。
static变量也称为静态变量,静态变量和非静态变量的区别:
- 静态变量被所有对象共享,在内存中只有一个副本,在类初次加载的时候才会初始化
- 非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响
==和equals的区别
1.对于==,比较的值是否相等
如果作用于基本数据类型的变量,则直接比较其存储的值是否相等
如果作用于引用类型的变量,则比较的是所指向的对象的地址
2.对于equals方法,注意:equals方法不能作用于基本数据类型的变量,equals继承Object类,比较的是是否是同一个对象,如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
例如String、Date等类对equals方法进行了重写的话,比较的是指向的对象的内容。
为什么要重写equals()和hashCode()方法
equals() 只是判断对象属性是否相同, hashcode() 要判断二者地址是否相同。
java中如果要判断两个对象是否相等,需要同时满足地址+属性都相同!
如果两个对象相同(即:用equals()比较返回true ),那么它们的 hashcode值一定要相同;
如果两个对象的hashcode()相同,它们并不—定相同;
(1)如果o1.equals(o2),那么o1.hashCode() == o2.hashCode()总是为true的。
(2)如果o1.hashCode() == o2.hashCode(),并不意味着o1.equals(o2)会为true。
final, finally, finalize的区别
- final用于声明属性方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 修饰变量:该属性一定要有初始值,要么在定义时马上初始化,要么在构造器中初始化。 该变量指向基本类型后该引用为常量,不能修改。 指向对象后,对象的引用不可变,但是对象的内容可变。 修饰方法:该方法无法被子类重写,但是可以被继承。 修饰类:该类无法被继承。比如java.lang.String类就是final类。 2) finaly是异常处理语句结构的一部分,表示总是执行,一定会执行。如果try里有一个return语句,会在return前执行finally中的代码。3) finalize是Object类的方法,执行gc时会调用此方法,可以覆盖此方法提供垃圾收集时其他资源的回收,比如关闭文件等。
请判断当一个对象被当作参数传递给一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
是值传递。java编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。
java中只有值传递,基本类型传递的是值的副本,引用类型传递的是引用的副本
说一下JVM/JRE/JDK区别
JVM = Java虚拟机
JRE = JVM 基础类库
JDK = JVM 基础类库 编译工具
Java异常体系
Throwable 是 Java 语言中所有错误或异常的超类。下一层分为 Error 和 Exception
Error :
是指 java 运行时系统的内部错误和资源耗尽错误。应用程序不会抛出该类对象。如果出现了这样的错误,除了告知用户,剩下的就是尽力使程序安全的终止。
Exception 包含:RuntimeException 、CheckedException
编程错误可以分成三类:语法错误、逻辑错误和运行错误。
语法错误(也称编译错误)是在编译过程中出现的错误,由编译器检查发现语法错误
逻辑错误指程序的执行结果与预期不符,可以通过调试定位并发现错误的原因
运行错误是引起程序非正常终端的错误,需要通过异常处理的方式处理运行错误
RuntimeException: 运行时异常,程序应该从逻辑角度尽可能避免这类异常的发生。
如 NullPointerException 、ClassCastException(类型强制转换异常) 、NullPointerException (空指针引用异常)、ArithmeticException(数学运算异常)、ArrayIndexOutOfBoundsException (下标越界异常)、NuberFormatException (数字格式不正常异常);
CheckedException: 受检异常,程序使用trycatch进行捕捉处理
如IOException、SQLException、NotFoundException;