Java基础篇(一)

Servet生命周期

●init()
在一个Servlet的生命周期中,init方法只会被执行一次。
●service()
当一个客户请求改Servlet时,实际的处理工作全部有service方法来完成,service方法用来处理客户端的请求,并生成格式化数据返回给客户端。
●destory();
该方法在整个生命周期中,也是只会被调用一次

序列化

序列化是为了解决在对对象流进行读写操作时所引发的问题。把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化(将对象转换成二进制)。

ObjectOutputStream.writeObject() 实现序列化
ObjectInputStream.readObject() 实现反序列化

各数据类型占多少字节

1个字节=8位
byte 1字节
short 2字节
int 4字节
long 8字节
float 4字节
double 8字节
char 2字节
boolean 1字节

反射的性能,如何优化

作用

①、在运行时判断任意一个对象所属的类
②、在运行时构造任意一个类的对象
③、在运行时判断任意一个类所具有的成员变量和方法(通过反射设置可以调用 private)
④、在运行时调用任意一个对象的方法

AOP/注解/分布式服务的服务端

性能

反射创建对象是几倍时间,获取成员变量和调用方法就是太多倍了。 
原因是在调用方法时,源码中遍历查找最为消耗时间。

优化方案 


1. m.setAccessible(true); 
由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的
2.用缓存,比如redis, 这个方法提高效率是显而易见的。 
将反射得到元数据保存起来,使用时,只需从内存中调用即可
3.利用一些高性能的反射库,如ReflectASM 
 

String,StringBuffer, StringBuilder 

String:String的值是不可变的,这就导致每次对String的操作都会生成新的String对象。
StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
Stringbuffer:可变字符串、效率低、线程安全;
StringBuilder:可变字符序列、效率高、线程不安全;

Statement与PreparedStatement的区别

Statement:
每次都会执行SQL语句,相关数据库都要执行SQL语句的编译。
Statement为一条Sql语句生成执行计划,
PreparedStatement:
Statement为一条Sql语句生成执行计划,
但是PreparedStatement的预编译结果会被缓存,下次执行相同的预编译语句时,就不需要编译,只要将参数直接传入编译过的语句执行代码  中就会得到执行,所以,对于批量处理可以大大提高效率。
作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。  

1、PreparedStatement尽最大可能提高性能。
2、极大的提高了安全性

Runtime

Runtime 类代表着Java程序的运行时环境,每个Java程序都有一个Runtime实例,该实例是单例的,该类会被自动创建,我们可以通过Runtime.getRuntime() 方法来获取当前程序的Runtime实例。

用途:
1、使用java代开本地可执行文件,例如调用shell。
2、打开一个程序,并用改程序打开一个支持的文件。
例如:打开记事本,用记事本打开java文件。
打开暴风播放器,用播放器打开一个本地视频。

浏览器的缓存机制

etag/last-modifyed/expires/cache-control
https://www.cnblogs.com/duiniweixiao/p/8884274.html

Session和Cookie区别

●session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象
●一个在客户端一个在服务端。因Cookie在客户端所以可以编辑伪造,不是十分安全。
●Session过多时会消耗服务器资源,大型网站会有专门Session服务器,Cookie存在客户端没问题。
●域的支持范围不一样,比方说a.com的Cookie在a.com下都能用,而www.a.com的Session在api.a.com下都不能用,解决这个问题的办法是JSONP或者跨域资源共享。
 

浏览器访问网址的分析

①查询ip地址
②建立tcp连接,接入服务器
③浏览器发起http请求
④服务器后台操作并做出http响应
⑤网页的解析与渲染
 

Java 重载和重写

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

Object的常用方法

●toString()
●equals()
●hashCode()
●notify()
●notifyAll()
●wait()

indexOf()和lastIndexOf()

indexOf() 是查某个指定的字符串在字符串首次出现的位置(索引值) (也就是从前往后查)
lastIndexOf() 方法有以下四种形式:
public int lastIndexOf(int ch): 返回指定字符在此字符串中最后一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。
public int lastIndexOf(int ch, int fromIndex): 返返回指定字符在此字符串中最后一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。
public int lastIndexOf(String str): 返回指定字符在此字符串中最后一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。
public int lastIndexOf(String str, int fromIndex): 返回指定字符在此字符串中最后一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。

switch的case如果没有break;就会顺序执行

int x = 3;
switch (x){

    case 2:
        x++;
    case 3:
        x++;
    case 4:
        x++;
    default:
        x++;
}
System.out.println(x);  x=6

float 会带有小数点

float a = 15/2;
Sys.out.print(a); a = 7.0

Boolean.parseBoolean(string)

String类型转boolean类型的一个方法。
当String的值为“true”时返回ture。
当为其他字符串时返回false。是boolean 类型。

for循环的int变量最后的值=小于号后面的值

for(int k=0;k<100;k++){
}
System.out.println(k);   k=100

java异常捕获


1、子类异常和父类异常同时存在,子类异常要放到父类异常之前,这样直接走子类异常,不会走父类异常。如果父类异常当到前面,子类异常放到后面,编译不会通过。

int i=10,j=0;
try{
    j+=i/j;
    System.out.println(j);
}catch (ArithmeticException e){
    System.out.println("AException");
}catch (Exception e){
    System.out.println("Exception");
}finally {
    System.out.println(j);
}

 \u202C,\u202D,\u202E是Excel文档中的非法字符

byte[]与各种数据类型互相转换

1.字节:byte:用来计量存储容量的一种计量单位;位:bit
2.一个字节等于8位  1byte = 8bit
char占用的是2个字节 16位,所以一个char类型的可以存储一个汉字。

整型:
byte:1个字节 8位 -128~127
short :2个字节 16位
int :4个字节 32位
long:8个字节 64位
浮点型:
float:4个字节 32 位
double :8个字节 64位
注:默认的是double类型,如3.14是double类型的,加后缀F(3.14F)则为float类型的。

char类型:
char:2个字节。
Boolean 类型
boolean: (true or false)(并未指明是多少字节  1字节  1位 4字节)

补充:BigInteger类实现了任意精度的整数运算,BigDecimal实现了任意精度的浮点数运算。
 

/**
 * 基础表示
 */
public void baseData(){
    //十进制默认
    int i_10 = 5;
    //八进制0开头
    int i_8 = 05;
    //十六进制0x开头
    int i_16 = 0x5;
    //二级制0b/0B开头
    int i_2 = 0b1;
    //<< :    左移运算符,num << 1,相当于num乘以2
    //>> :    右移运算符,num >> 1,相当于num除以2
    //>>> :   无符号右移,忽略符号位,空位都以0补齐
}


short转换为byte[]

/**
 * short到字节数组的转换
 * short占2个字节,转换为字节数组长度为2
 * 字节数组的第1个元素为short的低位,第2个为short的高位(大于255才有高位,即0xffff)
 * @param number
 * @return
 */
public static byte[] shortToByte(short number){
    int temp = number;
    byte[] b = new byte[2];
    for(int i=0;i> 8;// 向右移8位(取高8位)
    }
    return b;
}

byte[]转换short

/**
 * short到字节数组的转换
 * short占2个字节,转换为字节数组长度为2
 * 字节数组的第1个元素为short的低位,第2个为short的高位(大于255才有高位,即0xffff)
 * @param number
 * @return
 */
public static byte[] shortToByte(short number){
    int temp = number;
    byte[] b = new byte[2];
    for(int i=0;i> 8;// 二进制向右移8位(取高8位)
    }
    return b;
}

int转为byte[]

/**
 * int到byte[]的转换
 * @return
 */
public static byte[] intTpByte(int number){
    int temp = number;
    byte[] b = new byte[4];
    for (int i = 0; i < b.length; i++) {
        b[i] = new Integer(temp & 0xff).byteValue();// 将最低位保存在最低位  
        temp = temp >> 8;// 向右移8位  
    }
    return b;
}

Java注解

注释是绑定到程序源代码元素的元数据,对它们运行的​​代码的操作没有影响。

可以从注释方法声明返回哪些对象类型?

返回类型必须是基本类型,String,Class,Enum或以前类型之一的数组。否则,编译器将抛出错误。

有没有办法限制可以应用注释的元素?

@ Target注释可用于此目的。
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PACKAGE })

什么是元注释?

是否适用于其他注释的注释。
所有未标记为@Target的注释,或者使用它标记但包含ANNOTATION_TYPE常量的注释也都是元注释:

你怎么能检索注释?这与保留政策有何关系?

您可以使用Reflection API或注释处理器来检索注释。
该@Retention注解和其的RetentionPolicy参数会影响您检索它们。RetentionPolicy枚举中有三个常量:
RetentionPolicy.SOURCE - 使注释被编译器丢弃,但注释处理器可以读取它们
RetentionPolicy.CLASS - 表示注释已添加到类文件中,但无法通过反射访问
RetentionPolicy.RUNTIME -Annotations由编译器记录在类文件中,并由JVM在运行时保留,以便可以反射性地读取它们

下面的代码会编译吗?

@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.FIELD })
public @interface TestAnnotation {
int[] value() default {}; 
}


如果在@Target注释中多次出现相同的枚举常量,那么这是一个编译时错误。

是否可以扩展注释?

注释。注释总是扩展java.lang.annotation.Annotation,如Java语言规范中所述。
如果我们尝试在注释声明中使用extends子句,我们将得到一个编译错误:
 

Java如何实现LRU

LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉,比如我们缓存10000条数据,当数据小于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最大缓存10000条,那怎么确定删除哪条过期数据呢,采用LRU算法实现的话就是将最老的数据删掉,废话不多说,下面来说下Java版的LRU缓存实现
Java里面实现LRU缓存通常有两种选择,一种是使用LinkedHashMap,一种是自己设计数据结构,使用链表+HashMap

最近最少使用缓存的回收

为了实现缓存回收,我们需要很容易做到:
1、查询出最近最晚使用的项
2、给最近使用的项做一个标记

链表可以实现这两个操作。检测最近最少使用的项只需要返回链表的尾部。标记一项为最近使用的项只需要从当前位置移除,然后将该项放置到头部。比较困难的事情是怎么快速的在链表中找到该项。

LinkedHashMap的实现

LinkedHashMap自身已经实现了顺序存储,默认情况下是按照元素的添加顺序存储,也可以启用按照访问顺序存储,即最近读取的数据放在最前面,最早读取的数据放在最后面,然后它还有一个判断是否删除最老数据的方法,默认是返回false,即不删除数据,我们使用LinkedHashMap实现LRU缓存的方法就是对LinkedHashMap实现简单的扩展,扩展方式有两种,一种是inheritance(继承),一种是delegation(代理),具体使用什么方式看个人喜好:

//LinkedHashMap的一个构造函数,当参数accessOrder为true时,即会按照访问顺序排序,最近访问的放在最前,最早访问的放在后面

public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
}

//LinkedHashMap自带的判断是否删除最老的元素方法,默认返回false,即不删除老数据
//我们要做的就是重写这个方法,当满足一定条件时删除老数据

protected boolean removeEldestEntry(Map.Entry eldest) {
        return false;
}

guava的缓存是怎么实现的?

google guava中有cache包,此包提供内存缓存功能。
内存缓存需要考虑很多问题,包括:
●并发问题 
●缓存失效机制
●内存不够用时缓存释放
●缓存的命中率
●缓存的移除

guava中使用缓存需要先声明一个CacheBuilder对象,并设置缓存的相关参数,然后调用其build方法获得一个Cache接口的实例。

UML中的类关系

Java基础篇(一)_第1张图片

 

 

你可能感兴趣的:(面试题,Java)