0
点赞
收藏
分享

微信扫一扫

java 面试宝典总结

小月亮06 2022-03-12 阅读 101

面试宝典总结:

java 基础

Java 中的八种数据类型

四类八种字节数数据范围
整型byte1-128··127
整型short2-32768··32767
整型int4
整型long8-2^63 ·· 2^63-1
浮点型float4
浮点型double8
字符型char2
布尔型boolean1true,false

面向对象的四大特征:

  1. 继承:继承是从已有类得到继承信息,创建新类的过程。提供继承信息的类叫做父类,得到继承信息的类叫做子类。
  2. 封装:隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
  3. 多态:多态性指允许不同子类型的对象对同一消息做出不同的响应。(同样的对象引用调用同样的方法但是做了不同的事)多态必须满足的两个条件:1. 方法重写,2. 父类引用指向子类
  4. 抽象:抽象就是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象,抽象只关注对象有哪些属性和行为,不关心具体实现。

访问权限修饰符的区别

修饰符当前类同包子类其他包
public
protected×
default××
private×××

对象的克隆

克隆出来的对象是一个新的对象。
深拷贝和浅拷贝的区别:
当对象的中的对象是引用数据类型时,浅拷贝指向的时对象的引用,深拷贝才是新的创建。(Clone方法是浅拷贝)
在这里插入图片描述

如何实现深拷贝?

如果想深拷贝一个对象(对象中含有引用对象),这个对象非必须要实现Cloneable 接口,实现Clone方法,并且在clone方法内部,把该对象的引用的其他对象也要clone一份,这也意味者这个其他对象内部也要实现Cloneable接口,重写clone方法。

深克隆的方法验证

static class Body implements Cloneable {
    public Head head;

    public Body() {
    }

    public Body(Head head) {
        this.head = head;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Body newBody = (Body) super.clone();
        newBody.head = (Head) head.clone();
        return newBody;
    }
}

static class Head implements Cloneable {
    public Face face;

    public Head() {
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public static void main(String[] args) throws CloneNotSupportedException {
    Body body = new Body(new Head(new Face()));
    Body body1 = (Body) body.clone();
    System.out.println("body == body1 : " + (body == body1));
    System.out.println("body.head == body1.head : " + (body.head == body1.head));
}
/**
 * 程序执行结果:
 * body == body1 : false
 * body.head == body1.head : false
 */

& 和 && 的区别:

& :

  1. 位运算符 (可用于基本类型的数据运算(仅限byte,short,int,char,boolean))
  2. 逻辑与
    &&:短路与
    虽然& 和 && 运算符都要求左右两端的布尔值都是 true,整个表达式的结果才为true,但是短路与&& 运算符只有当左边的表达式为true时才会继续进行有右边等式的运算,右边为false时,会直接短路掉,右边的表达式不会执行。

java 中如何跳出当前的多重嵌套循环?

break关键字,在最外层循环加一个标记A,通过breakA;可以跳出多重循环

两对象的HashCode值比较。

如果两个对象equals方法返回true,那么它们的 hashCode 值一定相同。
两个对象的 hashCode 值相同,它们的equals方法不一定返回 true。(hash冲突)
A==B判断的两个对象的地址值是否相同,A.equals(B) 比较的是两个对象的值是否相同。
instanceOf 判断的是两个对象是否是同一个类型。

String 是否可以被继承?(final 修饰的类)

由于String 是被final修饰的类,所以不能被继承。

当一个对象被当作参数传递到一个方法后,方法可以改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

//基础类型作为值传递
public class test {
    public static void main(String[] args) {
        int i = 1;
        System.out.println("before change, i = "+i);
        change(i);
        System.out.println("after change, i = "+i);
    }
    public static void change(int i){
        i = 5;
    }
}
/**
 *  输出的结果是 before change i = 1;
 *  输出的结果是 after change i = 1;
 *  当基本数据类型作为参数传递时,传递的是实参值的副本,即传的是值,无论在函数中怎么操作这个副本, 
 *  实参的值是不会被改变的。
 */


//对象(引用类型)作为值传递
public class test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello ");
        System.out.println("before change, sb is "+sb.toString());
        change(sb);
        System.out.println("after change, sb is "+sb.toString());
    }
    public static void change(StringBuffer stringBuffer){
        stringBuffer.append("world !");
    }
}
/**
 * before change, sb is Hello
 * after change, sb is Hello world !
 */


/**
 * 从输出结果中我们可以发现,sb所指向的对象的值被改变了,那么是否我们可以推论出,在Java中,当 
 * 对象作为参数传递时,传递的是该对象的引用呢?我们再来看下面这个例子
 */

public class test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello ");
        System.out.println("before change, sb is "+sb.toString());
        change(sb);
        System.out.println("after change, sb is "+sb.toString());
    }
    public static void change(StringBuffer stringBuffer){
        stringBuffer = new StringBuffer("Hi ");
        stringBuffer.append("world !");
    }
}

/**
 * 如果上面的推论是正确的,即Java中对象作为参数传递,实际传递的是该对象的引用,那么在调用change 
 * 函数之后,原对象的值应该是会改变的,变为“Hi world !”,但是,当我们运行程序后,结果却是如下所示:
 * before change, sb is Hello
 * after change, sb is Hello
 *
 * 原对象的值并没有被改变,这与上面的推论相矛盾!
 */

/**
 * 总结就是基本数据类型传递的是形参,形参不影响实参;引用数据类型传递的是地址,形参在方法内被改变,实 
 * 参也会改变,若在方法内实例化了同名对象,即产生了新的地址,对这个同名对象的改变,由于地址不一样, 
 * 所以不影响原来的对象
 */

方法重载和方法重写的区别

方法的重载和方法的重写都是实现多态的方式。方法的重载是编译时的多态性,而方法的重写是运行时的多态性。

**方法重载的规则**
 - 方法名一致
 - 请求参数不同(个数不同,参数类型不同)
 - 和方法的返回值无关。
 - 可以抛出不同的异常,可以有不同的修饰符

**方法的重写**
 - 方法名,请求参数,返回值相同
 - 构造方法不能被重写,static 和 final 修饰的方法不能被重写
 - 重写的方法不能抛出被重写方法更广泛的异常。

抽象类 Abstract 和 interface 的区别?

相同: 都不能被实例化。
不同:抽象类中可以定义构造器,接口中不能定义构造器。接口中的成员全是public 的。抽象类中的成员可以是任何。抽象类中可以有成员变量,接口中没有。抽象类中可以有抽象方法和具体方法。接口中只有抽象方法。有抽象方法的类必须被声明成抽象类,但是抽象类中可以没有抽象方法 ,接口中的成员变量就是常量。抽象类中可以有静态方法。抽象类只能够单继承。接口可以多继承。

== 和 equal 的区别

一个是方法一个是运算符, == 如果比较的是基本类型的变量,则比较的是数值是否相等。如果比较的是引用类型,那么比较的是引用类型的地址值是否相等。 equal是用来比较两个对象的内容是否相等。equal是不能用来比较基本类型的。如果对象没有对equal 方法进行重写,那么equal方法比较的是对象的地址值;

String x = "string";
String y = "string";
String z = new String("string");
System.out.println(x==y); // true
System.out.println(x==z); // false
System.out.println(x.equals(y)); // true
System.out.println(x.equals(z)); // true
// new String() 方法是重写开辟了空间,所以 == 的结果为 false

equal 默认情况下是引用的比较(也就是 == 比较),不过很多的类都重写了 equal 方法,比如 String,Integer 等内部将equal 方法变成了 值 得比较。

break 和 continue 的区别

都是用来控制循环语句的。break 是用来结束一个循环的。continue 是用来跳过此次循环,执行下次循环。

throw 和 throws 的区别

throw 是用在方法体中的,用来抛出异常。执行throw 一定是抛出了某种异常。

throws 是用在方法生命后面的,表示可能会跑出某种异常。表示了某种异常的可能性,不一定会抛出异常。

final ,finally,finalize 的区别

final 修饰类,方法,属性,表示为最终态不可变。finally 异常处理语句结构的一部分,表示最终一定会被执行。finalize : Object 的一个方法,在垃圾回收器执行的时候会调用被回收对象的这个方法。更像是一个对象生命周期的临终方法,当此方法被调用代表着该对象的死亡。

final 修饰的类叫最终类,该类不能被继承
final 修饰的方法不能被重写
final 修饰的变量叫常量,常量必须初始化,初始化后不能再被修改

Math.round()方法

数据轴向右取整。 -11.5==》-11 11.5 ==》 12

switch 中可使用的类型

java 5 以前只能使用 byte,short,int ,char 。 java5 开始 引入了 enum 。 java7 后,引入了 String ,但是 Long 类型一直都是不可以的。

String,StringBuffer ,Stringbuild 的区别

String 是被final 修饰的。不能被修改,Stringbuild 的值是可以被修改的。 StringBuffer 是线程安全的类。被 Synchronized 修饰。

String 声明的是不可变的变量,每次操作都会生成新的String对象,而Stringbuild 和 Stringbuffer 都是在原字符串上进行操作的。StringBuild 是线程不安全的,推荐在单线程下使用,而StringBuffer 是线程安全的推荐在多线程下使用。

String str="i"与 String str=new String(“i”)一样吗?

不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

BIO,AIO,NIO 有什么区别?

BIO:同步阻塞式IO,简单方便,并发处理效率低
NIO:同步非阻塞IO,客户端和服务器通过channel 信道,实现了多路复用
AIO:NIO的升级,也叫NIO2。异步非阻塞IO

泛型

泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map。

public interface List<E> extends Collection<E> { 
    ........
}

//泛型的最基本写法:

classs 类名称<泛型标识:可以随便写任意标识符,标识指定的泛型的类型>{

      private 泛型标识  /* (成员变量类型) */  var ;

}

public void showKeyValue1(Generic<?> obj){
    Log.d("泛型测试","key value is " + obj.getKey());
}

JAVA 中的容器

常见的集合类: ArrayList,LinkedList,Vector,HashSet, TreeSet,HashMap , HashTable
list 中的元素可重复,set ,map 中的元素不可重复。

HashSet 和 HashMap

hashSet 的 底层是由 hashMap 实现的,HashSet 的值存放在 HashMap 的key 上,HashMap 的 value 统一是一个常量PRESENT。

ArrayList 和 LinkedList 的区别

ArrayList 的底层是数组,支持随机访问,LinkedList 的底层是双向循环链表,不支持随机访问。

Array 和 ArrayList 的区别

Array 只能存纳 基本数据类型的数据, 而ArrayList 只能容纳对象。

Sleep 和 wait 方法的区别

sleep():方法是线程类 Thread 的静态方法,让调用线程进入睡眠状态。 wait():是Object 类。 并且wait方法会释放锁。Sleep 方法不会释放锁。

线程池中的 submit ,和 execute 方法的区别?

接收到的参数不一样
submit 有返回值,而execute 没有
submit 方便 exception 处理
序列化,什么情况下需要序列化
当你想把内存中的对象状态保存到一个文件中或者数据库中的时候
当你想套接字在网络上传输对象时
当你想通过RMI传输对象时

什么是动态代理?

当想要给实现了某个接口的类中的方法,加一些额外处理时,比如说加日志,加事务。顾名思意就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处理的新类。这个代理类不是定义好的,是动态生成的。具有解耦意义。灵活拓展性强。

JAVAWEB

jsp 和 servlet 有什么区别?

jsp 经编译就成了 servlet 。(JSP 的本质就是 servlet )
servlet 中没有内置对象,JSP 中的内置对象都是必须通过 HttpServletRequset对象,HttpServletResponse对象以及HttpServlet 对象得到。

JSP 中有哪些内置对象?作用分别是什么?

  1. request: 封装客户端的请求,其中包含来自get或post请求的参数
  2. response:封装服务器对客户端的响应
  3. pageContext:通过该对象获取其他对象
  4. session:封装用户会话的对象
  5. application:封装服务器运行环境的对象
  6. out:输出服务器响应的输出流对象
  7. config:Web应用的配置对象
  8. page:JSP页面本身(相当于java 中的this)
  9. exception:封装页面抛出异常的对象

JSP 的四种作用域对象?

page :代表与页面相关的对象和属性
request :代表web 客户机发出的一个请求相关的对象和属性,一个请求可以跨越多个页面,涉及多个web 组件,需要在页面显示的临时数据可以置于此作用域
session :代表与整个用户和服务器建立的一次会话相关的对象和属性,跟某个用户相关的数据应该放在用户自己的session 中。
application :代表与整个 web 应用程序相关的 对象和属性,它实质上是 跨越整个web 应用程序,包括多个页面,请求和会话的一个全局作用域。

Session 和 Cookie 的区别

由于http 是无状态的协议,所以服务器需要记录用户的状态时,就需要某种机制来识别具体用户,这个机制就是session,
典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的session,用来标识这个用户,并且跟踪用户。 这个session 是保存在服务端的,有一个唯一标识,在服务端保存session的方法有很多,内存,数据库,文件都有。集群的时候也要考虑session的转移,在大型的网站,一般都有专门的session服务器集群,用来保存用户的会话信息。
思考一下服务端如何识别特定的客户?cookie 的作用就是用来识别客户。每次http 请求的时候,客户端都会发送相应的cookie信息到服务端,(实际上大多数的应用都是利用cookie 来实现 session 跟踪的),第一次创建session 的时候,服务端会在http 协议中告诉客户端,需要在cookie 里面记录一个sessionID,以后每次请求都把这个会话ID 发送到服务端。这样我就能知道你是谁了,(如果cookie 被禁用了怎么办?一般这种情况下,会使用一种叫做URL重写的技术来实现会话跟踪,即每次http交互,URL后面都会被附加上一个诸如sid=xxx这样的参数,服务端据此来识别用户)
session 是在服务器保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群数据库,文件中。Cookie 是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现session的一种方式。

session 的工作原理

session 是存在服务器上的类似于一个散列表格的文件。里面存有我们需要的信息,在我们需要的时候可以从里面取出来,类似于一个大号的map。里面的键存储的是用户的sessionId,用户向服务器请求就会带上这个key。

如果客户端禁用cookie ,session 还能用么?
不能,sessionID 是通过 cookie 来传递的,禁用cookie 相当于失去了 sessionId。

其他实现途径:手动通过URL传值,隐藏表单传递sessionID, 用文件、数据库等形式保存 sessionID,在跨页过程中手动调用。

举报

相关推荐

0 条评论