java面试题

作者: z七夜 | 来源:发表于2018-05-17 13:19 被阅读39次

    写在前面:本文参照网上资源编写,如有侵权请联系删除,如有错误请指正,谢谢(主要是做个笔记,怕以后找不到)

    java基础

    1.1接口与抽象类的区别

    含有abstract修饰符的class即为抽象类,abstract类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。

    接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。

    下面比较一下两者的语法区别:

    1.抽象类可以有构造方法,接口中不能有构造方法。

    2.抽象类中可以有普通成员变量,接口中没有普通成员变量

    3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

    1. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然
      eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
    2. 抽象类中可以包含静态方法,接口中不能包含静态方法
    3. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
    4. 一个类可以实现多个接口,但只能继承一个抽象类。
      下面接着再说说两者在应用上的区别:
      接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,可以实现代码的重用,

    1.2threadLocal类

    ThreadLocal类用于创建一个线程本地变量

    在Thread中有一个成员变量ThreadLocals,该变量的类型是ThreadLocalMap,也就是一个Map,它的键是threadLocal,值为就是变量的副本。通过ThreadLocal的get()方法可以获取该线程变量的本地副本,在get方法之前要先set,否则就要重写initialValue()方法。

    ThreadLocal的使用场景:

    数据库连接:在多线程中,如果使用懒汉式的单例模式创建Connection对象,由于该对象是共享的,那么必须要使用同步方法保证线程安全,这样当一个线程在连接数据库时,那么另外一个线程只能等待。这样就造成性能降低。如果改为哪里要连接数据库就来进行连接,那么就会频繁的对数据库进行连接,性能还是不高。这时使用ThreadLocal就可以既可以保证线程安全又可以让性能不会太低。但是ThreadLocal的缺点时占用了较多的空间。

    1.3 java组件(专业术语说不来)

    jar 将许多文件组合成一个jar文件

    javac 编译

    javadoc 它从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档。

    javah 把java代码声明的JNI方法转化成C\C++头文件。 JNI可参考java核心技术卷二第12章

    1.4==和equals的区别

    因为== 表示的是否指向的是同一个内存。

    System.out.println(classa.equals(classb)); 如果这这样输出 答案也是错误的 因为子类没有覆盖Object

    的equals()方法,而默认调用==的这个方法 判断两个对象是否相等需要覆盖equals()方法和hashcaode()方法

    string类equals判断内容。==判断地址

    String 类给我们覆盖了equals和hashCode方法了。所以我们可以直接判别字符串,但是这个自定义的类没有给我们覆盖,

    1.5 类初始化顺序

    1. 初始化父类中的静态成员变量和静态代码块 ;
    2. 初始化子类中的静态成员变量和静态代码块 ;
    3. 初始化父类的普通成员变量和普通代码块,再执行父类的构造方法;
    4. 初始化子类的普通成员变量和普通代码块,再执行子类的构造方法;
      另外,静态代码块和静态成员变量,普通代码块和普通成员变量分别属于同一级别,按顺序加载

    1.6重写与重载

    1.6.1重载

    java重载的时候以参数个数和类型作为区分,方法名相同,返回类型可以相同也可以不同,但不以返回类型作为区分,所以b也是错的,因为b的参数列表和原来的一样

    1.6.2 重写

    复习一下子类方法重写父类方法遵循“两同两小一大”的规则

    子类覆盖父类要遵循“两同两小一大”

    “两同”即方法名相同,形参列表相同

    “两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等。

    (注:看到有网友有这样的疑问,父类方法返回值是double,子类修改成int为什么不行呢?

    这是因为返回值类型更大或者更小,是对于同一类型而言的。也就是说,返回值的类型需要有继承关系才去考虑大小这个概念。类型不同,肯定不是方法重写)

    “一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。

    注意:覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法一个是实例方法,否则编译出错。

    1.7String类

    String 字符串常量

    StringBuffer 字符串变量(线程安全)

    StringBuilder 字符串变量(非线程安全)

    String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都是String类的对象。字符串是常量;它们的值在创建之后不能改变。所以可以共享它们。StringBuffer是字符串缓存区,它的内容可以被修改,长度也可以改变,StringBuffer类是线程安全的,也就是说多个线程可以安全的访问StringBuffer对象。StringBuilder与StringBuffer类似,都是字符串缓冲区,但StringBuilder不是线程安全的,如果你只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会更高些。值得注意的是StringBuilder是在JDK1.5版本中增加的。以前版本的JDK不能使用该类。

    1.8 集合

    1.8.1 Vector & ArrayList 的主要区别

    Vector & ArrayList 的主要区别

    1) 同步性:Vector是线程安全的,也就是说是同步的 ,而ArrayList 是线程序不安全的,不是同步的 数2。

    2)数据增长:当需要增长时,Vector默认增长为原来一倍 ,而ArrayList却是原来的50% ,这样,ArrayList就有利于节约内存空间。

    如果涉及到堆栈,队列等操作,应该考虑用Vector,如果需要快速随机访问元素,应该使用ArrayList 。

    1.8.2 ArrayList和linklist区别

    ArrayList的内部实现是基于内部数组Object[],所以从概念上讲,它更象数组,但LinkedList的内部实现是基于一组连接的记录,所以,它更象一个链表结构,所以,它们在性能上有很大的差别:

    1.8.3 map

    hashmap:线程不安全,值和key都可以为null

    hashtable:线程安全,key和值都不能为null,可以为“”

    1.9 Java虚拟机内存

    Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

    堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。

    运行时数据区包括:虚拟机栈区,堆区,方法区,本地方法栈,程序计数器

    虚拟机栈区 :也就是我们常说的栈区,线程私有,存放基本类型,对象的引用和 returnAddress ,在编译期间完成分配。

    堆区 , JAVA 堆,也称 GC 堆,所有线程共享,存放对象的实例和数组, JAVA 堆是垃圾收集器管理的主要区域。

    方法区 :所有线程共享,存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。这个区域的内存回收目标主要是针对常量池的对象的回收和对类型的卸载。

    程序计数器 :线程私有,每个线程都有自己独立的程序计数器,用来指示下一条指令的地址。

    泛型不会影响程序运行速度

    2.0 java语言类型

    基本类型:boolean类型,数值类型:整数类型(byte,short,long,char),浮点类型(double,float)

    引用类型:类,接口,数组类型,null类型

    2、多线程

    1.1、线程定义

    要写一个线程类,可以继承Thread方法,然后override他的run()方法

    另一种方法是实现Runable接口,即为实现run()方法。

    实现callable接口,

    start()是启动一个线程的方法

    sleep是线程类(thread)的方法,wait是Object类的方法,

    sleep不释放对象锁,wait放弃对象锁

    sleep暂停线程,但监控状态仍然保持,结束后会自动恢复

    1.2、 多线程间通信

    多线程之间通信 共享内存变量,消息传递 Java使用共享内存变量

    多线程之间为什么会出现线程安全或线程不安全(结果与预期结果不一样) 以为Java内存模型(jmm) 每个线程有自己的内存,对变量的操作是拷贝主存数据到自己的内存区域,然后由jmm决定某时进行数据同步到主存,如果在没有同步的时候,另一个线程读取数据,就会出现数据脏读,线程不安全,解决办法 使用volatile关键子,强制刷新到主存,或使用同步机制(控制线程执行顺序)

    1.3、happen before

    a happened before b 线程a的操作对b可见

    3.spring

    1.1spring事务传播

    propagation_supports:支持当前事务,如果当前没有事务,就以非事务方式执行

    propagation_required:支持当前事务,如果当前没有事务。就新建一个事务

    propagation_requires_new:新建事务,如果当前存在事务,就把当前事务挂起

    propagation_nested:支持当前事务,新增savepoint点,与当前事务同步提交或回滚

    propagation_mandatory:表示方法必须运行在一个事务中,如果当前事务不存在,就抛出异常,

    propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起

    propagation_never : 以非事务方式执行,如果当前存在事务,则抛出异常

    1.2 spring七大模块

    1.spring core: core封装包是框架最核心的部分,提供了ioc和依赖注入的特性,这里的基础概念是BeanFactory,它提供了对Factory模式的经典实现来消除对程序性单例模式的需要,并真正的允许你从程序中分理处依赖关系和配置

    2.spring context:构建与core包的基础之上,提供了一种框架式的对象访问方法,有点像jndi的注册器,context封装包的特性得自于beans封装包,并添加了对国际化的支持,事件传播,资源装载的方式和context的透明创建,

    3.spring dao:dao层提供了jdbc的抽象层,他可消除冗长的jdbc编码和解析数据库厂商的特有的错误代码,并且,jdbc封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的pojo都适用

    4.spring orm:orm封装了常用的对象关系,映射apis的集成层,其中包含jpa,jdo,hibernate和ibatis,利用orm封装包,可以混合使用所有的spring提供的特性进行对象,关系映射,如前面提到的声明式事务管理

    5.spring aop: spring的aop提供了符合aop规范的面向方面的编程实现,让你可以定义,例如方法拦截器,和切点,从逻辑上,减弱代码的功能耦合,清晰的被分离开,而且,利用source-level的元数据,可以将各种行为信息合并到你的代码中,

    6,spring web mvc: spring中的mvc提供了web应用的mvc实现,spring的mvc框架并不是仅仅提供了一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码,和webform之间,并且,还可以接种spring的其他特性。

    7.spring web: 提供了基础的针对web开发的集成特性,例如多方文件上传,利用servlet listeners进行ioc容器初始化和针对applicationcontext,当与webwork或struts一起使用spring时,这个包使spring可与其他框架结合

    1.3springmvc原理

    用户发送请求到达springmvc的前端控制器(dispatcherservlet) 前端控制器根据永华的url请求处理映射器查找匹配该url的handler,并返回一个执行链,前端控制器在请求处理器适配器调用相应的handler进行处理并返回给前端控制器一个modelandview,前端控制器再请求视图解析器对返回的逻辑视图进行解析,最后前端控制器将返回的视图进行渲染并把数据装入到request域中,返回给用户

    dispatcherservlet作为springmvc的前端控制器,负责接收用户的请求并根据用户请求返回相应的视图给用户

    1.4 spring的注入方式

    设值注入

    构造注入

    在没有设值注入的情况下才会根据配置文件中的构造注入,一旦有设值注入,则构造注入失败

    群号:552113611

    相关文章

      网友评论

      本文标题:java面试题

      本文链接:https://www.haomeiwen.com/subject/dnxxdftx.html