Javase复习
一、面向对象的特征
- 抽象
- 继承
- 封装
- 多态性
二、final、finally、finalize的区别?
- final:修饰类、修饰方法、修饰变量
- finally:finally作为异常处理的一部分,它只能用在try/catch中,并且附带一个语句块,表示这段语句最终一定被执行。
- finalize:finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这个方法。这个方法在gc启动,该对象被回收时候调用。
三、int 和 Integer 有什么区别?
int是基本数据类型,integer是int的包装类型。
四、强引用、软引用、弱软用、虚引用区别?
强引用:如果一个对象具有强引用,那么垃圾回收器绝不会回收它。
Object object = new Object();
String str = "StrongReference";
软引用:内存足够时、垃圾回收器就不会回收;若是内存不够,垃圾回收器就会回收。
public static void main(String[] args){
Obj obj = new Obj();
SoftReference<Obj> sr = new SoftReference<Obj>(obj);
obj = null;
System.out.println(sr.get());
}
弱引用:无论内存够不够,垃圾回收器扫描到都会回收它。
public static void main(String[] args) {
WeakReference<String> sr = new WeakReference<String>(new String("hello"));
System.out.println(sr.get());
System.gc(); //通知JVM的gc进行垃圾回收
System.out.println(sr.get());
}
虚引用:虚引用不会决定对象的生命周期,任何时候都有可能被回收。
主要用来跟踪对象被垃圾回收器回收的活动。
public static void main(String[] args) {
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
System.out.println(pr.get());
}
五、重载和重写的区别?
- 重写:发生在父类子类之间,方法名相同,参数列表相同。
- 重载:发生在一个类里面,方法名相同,参数列表不同。
六、说说反射的用途及实现
反射是什么:反射允许动态地发现和绑定类、方法、字段,以及所有其他的由于有所产生的元素。通过反射,能够在需要时完成创建实例、调用方法和访问字段的工作。
反射机制主要提供功能:
- 在运行时构造任意一个类的对象
- 在运行时调用任意一个对象的方法
- 生成动态代理
class对象的获取及使用:
class.forName(“全类名”)
源代码阶段,它能将字节码文件加载进内存中,然后返回Class对象,多用于配置文件中,将类名定义在配置文件中,通过读取配置文件来加载类。
类名.calss:
类对象阶段,通过类名class属性来获取,多用于参数的传递。
对象.getClass():
运行时阶段,getCLass()定义在Object类中,表明所有类都能使用该方法,多用于对象的获取字节码方式。
获取对象:
- Class class1 = Class.forName(“com.cunyu.Person”);
- Class class2 = Person.class;
- Person person = new Person();
Class class3 = person.getClass();
获取成员变量:
Class class1 = Class.forName(“com.cunyu.Person”);
Field[] fields = class1.getFields(“变量名”);
获取构造方法:
Class personClass = Class.forName(“com.cunyu.Person”);
Constructor[] constructors = personClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
Constructor constructor2 = personClass.getConstructor(int.class, String.class, long.class, long.class, float.class, int.class);
// 第一种方法
Object person = constructor1.newInstance();
System.out.println(person);
// 第二种方法
Object person1 = personClass.newInstance();
System.out.println(person1);
获取成员方法:
Class personClass = Class.forName(“com.cunyu.Person”);
Method getAgeMethod = personClass.getMethod(“getAge”);
Person person = new Person(20, “村雨遥”, 1312020, 3, 99.0F, 2);
int age = (int) getAgeMethod.invoke(person);
获取类名:
Person person = new Person();
Class personClass = person.getClass();
String className = personClass.getName();
System.out.println(className);
七、说说自定义注解的场景及实现
应用场景一:自定义注解+拦截器 实现登录校验
首先定义一个LoginRequire注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
}
然后写两个简单的接口,访问sourceA,sourceB资源:
@RestController
public class IndexController {
@GetMapping("/sourceA")
public String sourceA(){
return "你正在访问sourceA资源";
}
@GetMapping("/sourceB")
public String sourceB(){
return "你正在访问sourceB资源";
}
}
实现spring类WebMvcConfigurer,创建配置类把拦截器添加到拦截器链中:
在sourceB方法上添加我们的登录注解@LoginRequired:
简单实现登录拦截逻辑;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("进入拦截器了");
// 反射获取方法上的LoginRequred注解
HandlerMethod handlerMethod = (HandlerMethod)handler;
LoginRequired loginRequired = handlerMethod.getMethod().getAnnotation(LoginRequired.class);
if(loginRequired == null){
return true;
}
// 有LoginRequired注解说明需要登录,提示用户登录
response.setContentType("application/json; charset=utf-8");
response.getWriter().print("你访问的资源需要登录");
return false;
}
运行成功,访问sourceB时需要登录了,访问sourceA则不用登录;
应用场景二:自定义注解+Aop实现日志打印:
先导入切面需要的依赖包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
定义一个注解@MyLog:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}
定义一个切面类:
@Aspect // 1.表明这是一个切面类
@Component
public class MyLogAspect {
// 2. PointCut表示这是一个切点,@annotation表示这个切点切到一个注解上,后面带该注解的全类名
// 切面最主要的就是切点,所有的故事都围绕切点发生
// logPointCut()代表切点名称
@Pointcut("@annotation(me.zebin.demo.annotationdemo.aoplog.MyLog)")
public void logPointCut(){};
// 3. 环绕通知
@Around("logPointCut()")
public void logAround(ProceedingJoinPoint joinPoint){
// 获取方法名称
String methodName = joinPoint.getSignature().getName();
// 获取入参
Object[] param = joinPoint.getArgs();
StringBuilder sb = new StringBuilder();
for(Object o : param){
sb.append(o + "; ");
}
System.out.println("进入[" + methodName + "]方法,参数为:" + sb.toString());
// 继续执行方法
try {
joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println(methodName + "方法执行结束");
}
}
在步骤二中的indexController写一个sourceC进行测试,加上我们的自定义注解:
@MyLog
@GetMapping("/sourceC/{source_name}")
public String sourceC(@PathVariable("source_name") String sourceName){
return "你正在访问sourceC资源";
}
八、HTTP 请求的 GET 与 POST 方式的区别
- GET是把参数包含在URL中,POST通过request body传递参数。
- post更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器记录中)
- post发送的数据更大
- post能发送更多的数据类型
- post比get慢
- post用于修改和写入数据,get一般用于搜索和筛选之类的操作
九、如何解决ajax跨域
- JSONP方式
- CORS方式
- 代理请求方式
使用jquery实现:在请求的地址后面加上?callback=?,将配置项中的dataType属性,设置为jsonp。
十、session 与 cookie 区别?
1.存储位置不同:cookie存储在浏览器中,session存放在服务器上
2.存储容量不同:单个cookie保存的数据<=4KB,一个站点最多保存20个cookie。session没有上限,但出于对于服务器的性能考虑,session不要存放过多的东西,并设置session删除机制。
3.存取方式不同:cookie只能保管ASCLL字符串
4.隐私策略不同:cookie对客服端是可见的
5.有效期不同:可以通过设置cookie的属性:达到cookie长期有效的效果,session不能达到长期有效的效果。
6.跨域支持上不同:cookie支持跨域名访问,session则不会支持跨域名访问。
十一、JDBC 流程
1.导入数据库连接包,自动注册驱动;
2.跟数据库进行连接,通过数据库驱动获取一个数据库连接对象Connection;连接的方式就是DriverManager中的getConnection(String url, String user, String password)方法;
3.通过Connection对象创建一个sql语句的执行对象Statement;
4.调用Statement里的对应两个方法executeUpdate/executeQuery,执行相应的sql语句,并得到返回结果。
5.释放资源。Connection和Statement需要释放资源,调用close方法即可。
十二、MVC设计思想
(1) M(Model) 模型:处理业务逻辑,对应组件是JavaBean(Java类);
(2) V(View)视图层:显示查询结果、收集用户数据,对应组件是jsp或html文件;
(3) C(Controller)控制器层:接收 view 请求并将请求转交给对应的 Model 并向客户端作出相应,对应组件是Servlet;
(4) 作用:实现了代码的分离,降低耦合度。
MVC设计模式的好处:
- 各司其职、互不干涉
- 有利于在开发中的分工
- 有利于组件的重用
十三、equals 与 == 的区别
1.对于==,一般比较的是值是否相等
- 如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
- 如果作用于引用类型的变量,则比较的是所指向的对象的地址
2.对于equals方法,一般为比较内容是否相同
- 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
- 诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
十四、构造器是否可被重写
构造器不能被继承,因此不能被重写,但可以被重载。
十五、描述一下JVM加载class文件的原理机制?
JVM中类的加载是由类加载器和它的子类来实现的,Java中的类加载器是一个重要的java运行时系统组件,它负责在运行时查找和装入类文件中的类。
十六、抽象类和接口有什么异同?
- 抽象类和接口都不能实例化,但可以定义抽象类和接口类的引用。
- 抽象类中的成员可以时private\默认、provted、public的,而接口中的成员全部都是public的。
- 抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。
- 有抽象方法的类必须被声明为抽象类,而抽象类未必有抽象方法。
十七、JAVA对象创建的方式有哪些?
- 使用new关键字
- 使用class类的newInstance()方法
- 使用Constructor类的newInstance()方法
- 使用clone()方法