java初级面试

java初级面试

java如何实现跨平台(关键字jvm)
我们编译后的Java代码,会生成一种 .class 文件,也就是字节码文件。
字节码不能直接运行,必须通过JVM翻译成机器码才能运行。
Java虚拟机就是负责将字节码文件翻译成特定平台下的机器码然后运行。
JVM(Java虚拟机)也是一个软件,不同的平台有不同的版本。只要在不同平台上安装对应的JVM,就可以运行字节码文件。
同一个Java程序,通过JVM这一”中间层“,就能在不同平台上运行,实现了”一次编译,到处运行“JVM是实现跨平台的关键
注意:编译的结果不是生成机器码,而是生成字节码,不同平台下编译生成的字节码是一样的,但是由JVM翻译成的机器码却不一样

1.面向对象的特征有哪些?有哪些原则?

特征
封装:是把数据和操作数据的方法包装起来,对数据的访问只能通过已定义的接口
继承:子类继承父类的特征和行为 属性(非private)子类也可以对父类进行扩展
抽象:抽出它们最本质的东西,忽略掉其他部分 数据抽象和行为抽象
多态:同一个事件发生在不同的对象上会产生不同的结果

多态存在的三个必要条件
继承
重写
父类引用指向子类对象

重载(Overload)和重写(Override)的区别?
重载:在同一个类中 方法相同参数不相同 参数类型不同 重载对返回类型没有特殊的要求
重写:子类重写父类方法要求方法名、方法的参数都相同返回类型也相同

解释内存的栈(stack)、堆(heap)和方法区(method area)的用法.
堆区: 存储的全部是对象被所有线程共享
堆是一块很大的区域 所有通过new关键字都存放在堆中
当超过堆内存大小 会出现内存溢出 为保证程序稳健运行
通过GC(垃圾回收器)去控制对象的量回收没有用到的对象
Survivor区:年老代对象: 多次扫描没被回收
Eden区:年轻代对象: 新new的对象

栈区:栈是线程执行的轨迹,用于存储运行变量的指针栈 性质是先进后出,后进先出;
(栈空间是byte字节 大小 -127-128 超出范围 算new存放在堆中)
一个线程会分配一个栈
八大基本数据类型直接把值压栈其他压栈地址
String(字符串)的对象只有堆能存 因为量大

方法区:方发区被各个线程共享,用于存储已经被JVM加载的类信息、常量、静态变量。

描述一下JVM加载class文件的原理机制
JVM(JAVA Virtual Machine)中类的装载是由类加载器(ClassLoader)和它的子类来实现的
他 有层级关系
启动类加载器:负责加载JDK\jre\lib jar包
扩展类加载器:负责加载JDK\jre\lib\ext jar包
应用程序类加载器:负责加载自己的类jar包
自定义类加载器:程序上线时给你一个jar包 让你调用这个jar包里面的某个方法 这个时候就能使用自定义加载器

String和StringBuilder、StringBuffer的区别?
StringBuilder:字符串变量 线程不安全的 效率高
StringBuffer:字符串变量 线程安全的
String:字符串常量 不可变字符串

Java 中内存泄露和内存溢出区别
内存泄露:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出
内存溢出:指程序申请内存时,没有足够的内存供申请者使用
栈溢出(递归java.lang.StackOverflowError)是递归太深(自己调自己)
栈先入后出,递归的话那么先入的一致不能出栈,会一致存在栈空间中

Java语言如何进行异常处理,关键字:throws、throw、
try、catch、finally分别如何使用

throws:申明抛出异常
throw:抛出异常
try:可以出现异常的代码块
catch:扑捉特定类型异常
finally:最终执行的代码块

阐述静态变量和实例变量的区别。
静态变量需要static关键字修饰,实例变量不需要。
静态变量属于类,实例变量属于对象。
实例变量必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量;
静态变量即类别量,只要程序加载了类的字节码,静态变量就会被分配空间,即可使用。

如何实现对象克隆
1.实现Cloneable接口并重写Object类中的clone()方法;
2.实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆
3.使用第三方库克隆commons-bean

GC是什么?为什么要有GC
GC:垃圾回收一个单独的低优先级的线程运行
回收无用对象占用的内存空间。使该空间可被程序再次使用

Error和Exception有什么区别
答:Error表示系统级的错误和程序不必处理的异常;Exception表示需要捕捉或者需要程序进行处理的异常.

列出一些你常见的运行时异常

  • ArithmeticException(算术异常)
  • ClassCastException (类转换异常)
  • IndexOutOfBoundsException (下标越界异常)
  • NullPointerException (空指针异常)
    ClassNotFound (类找不到异常)
    非运行异常
    IoException
    sqlException

阐述final、finally、finalize的区别
final:被修饰的类不能被继承,修饰的变量成常量只能赋值一次,不能改变 方法不能被重写
finally:通常放在try…catch…的后面,程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行可以将释放外部资源的代码写在finally块中
finalize:垃圾回收 finalize是方法名可以通过重写finalize()方法可以整理系统资源或者执行其他清理工作

hashmap实现原理[重点]
数组和链表优点产生的新的集合(键值对)
Hashmap 插入数据 对key进行hash(hash计算下标) 返回int值就决定当前的键值对被放入set的位置(下标)
如果新插入的键值对的key的hash和某个key的hash一致 就以链表的形式存放在之前key的下一个位置

进程和线程区别
进程:一个程序要执行了就是进程,进程至少有一个线程
线程:是进程中能够独立运行最小运行单位

Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别
答:sleep()方法(休眠)是线程类(Thread)的静态方法,对象的锁依然保持,因此休眠时间结束后会自动恢复 。
wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。

线程的sleep()方法和yield()方法有什么区别
sleep()方法给其它线程运行时,不考虑线程的优先级;而yield()方法只会给相同优先级或更高优先级的线程运行的机会。
执行sleep()方法后会转入阻塞状态,所以线程在指定的时间内肯定不会被执行;而yield()只是使当前线程重新回到可执行状态,马上又会被执行。
sleep()方法声明抛出InterruptedException;而yield()没有声明任何异常。
sleep()方法比yield()方法具有更好的可移植性

什么是线程池(thread pool)
减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
线程池是用多个工作线程和阻塞队列组成的。
提交到线程池中的线程统称为任务,任务被提交阻塞队列中
工作线程死循环从工作队列中获取任务 调用run方法
常见的工作线程池
单工作线程线程池newSingleThreadExecutor
固定大小工作线程线程池newFixedThreadPool
可缓存工作线程线程池newCachedThreadPool

优化jvm
堆内存不足:–Xmx
方法区(用户内存)内存不足:-XX:MaxPermSize
线程栈大小不足 :-Xss

线程死锁的原因
多个线程互相锁定资源 同步块中获取对方锁 会造成死锁
解决的方案就是要考虑执行的顺序问题

多线程怎么处理并发?
线程是可以独立运行的最小单元 线程并发可以提高cpu的利用率,提高并发量的同时
考虑一些基本的问题 线程安全问题 涉及到同步锁 (wait notify sleep join)等同步调度
考虑创建线程消耗的资源问题 应该使用线程池运行线程

ThreadLocal是什么
因为多个线程操作同一个共享变量存在线程安全问题, 此时使用ThreadLocal通过set方法保存共享变量,,不同线程操作该ThreadLocal共享变量时实际上是操作当前线程的一份拷贝,而不会影响其他线程。
ThreadLocal常用三个操作:
1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。
2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。
3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。
使用这种存储结构的好处:
线程结束的时候,线程共享变量ThreadLocalMap则销毁。

简述synchronized 和java.util.concurrent.locks.Lock的异同
答:Lock比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且最好在finally 块中释放(这是释放外部资源的最好的地方)

阐述JDBC操作数据库的步骤
• 加载驱动。
• 创建连接。
• 创建语句。
• 执行语句。
• 处理结果。
• 关闭资源。

简述一下面向对象的"六原则一法则"

  • 单一职责原则:一个类只做它该做的事情。
  • 开闭原则:软件实体应当对扩展开放,对修改关闭。
  • 依赖倒转原则:面向接口编程。
  • 里氏替换原则:任何时候都可以用子类型替换掉父类型。
  • 接口隔离原则:接口要小而专,绝不能大而全。
  • 合成聚合复用原则:优先使用聚合或合成关系复用代码 尽量少使用继承。
  • 迪米特法则:迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。

简述一下你了解的设计模式
答:就是一套被反复使用的代码设计经验的总结,使用设计模式是为代码更容易被他人理解、保证代码可靠性和重用性,设计模式总共有23种,在代码中暂时没有考虑过,自己有了解的设计模式只有:

  1. 单例模式:某个对象的实例只需要创建一个实例,有两种构建方式:
    懒汉方式。指全局的单例实例在第一次被使用时构建。
    饿汉方式。指全局的单例实例在类装载时构建
  2. 工厂模式
    工厂模式是用工厂方法代替new操作的一种模式,降低了对具体实现的依赖,工厂负责生产某个接口对应的实例,只需要通过传入特定标识即可获取对象实例,将来修改代码只需要修改工厂类,给你系统带来更大的可扩展性和尽量少的修改量。spring的容器就是一个典型工厂模式

Hashmap和hashtable线程安全问题
HashTable是线程同步的、不允许空的键值,线程是安全的;
HashMap是线程不同步的、允许空的键值、线程是不安全的;相对HashTable效率高点;所谓线程不同步,是指多个线程访问时必须加Synchronized关键字;

接口和抽象的区别?
1.抽象可以有构造方法, 接口没有
2.抽象类的成员变量可以是各种类型, 接口只能是常量
3.抽象类中可以有静态方法和静态代码块,接口不可以

用Java写一个单例类
答:

  • 饿汉式单例

  • 指全局的单例实例在类装载时构建

     public class Singleton {
          private Singleton(){}
          private static Singleton instance = new Singleton();
          public static Singleton getInstance(){
              return instance;
          }
      }
    

• 懒汉式单例
• 指全局的单例实例在第一次被使用时构建。

public class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
    public static synchronized Singleton getInstance(){
        if (instance == null) instance = new Singleton();
        return instance;
    }
}

编写多线程程序有几种实现方式
答:Java 5以前实现多线程有两种实现方法:一种是继承Thread类;另一种是实现Runnable接口。两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。实现Callable接口,该接口中的call方法可以在线程执行结束时产生一个返回值.

请说出与线程同步以及线程调度相关的方法

  • wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
  • sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;
  • notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
  • notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;

Collection和Collections的区别?
Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。

List、Map、Set三个接口存取元素时,各有什么特点
List:可以有重复元素
Set:不能有重复元素
Map:键值对存储不能存储重复的key

阐述ArrayList、Vector、LinkedList的存储性能和特性
ArrayList:和Vector他们底层的实现都是一样的,都是使用数组方式存储数据 查询修改快而增
加删除慢ArrayList非线程安全的
Vector:Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList慢.
LinkedList:双向链表实现存储 增加删除速度较快查询修改慢(指针) 非线程安全的

八个基本类型 以及对应的包装类

  • byte Byte
  • short Short
  • int Integer
  • long Long
  • float Float
  • double Double
  • char character
  • boolean Boolean

list和set的区别?
set:无序自动去重 对象 为什么会去重 是因为通过HashMap键实现的存值 HashMap键不能重复
list:允许重复 有顺序 数组

list和数组的区别
数组:长度是固定的 数组只能存放类型一样的数据
list:长度可动态扩展 可以存储任意类型对象

集合与数组有什么区别
数组:下标访问 效率比集合高 存放类型一样的数据 长度固定
集合:集合内部是用数组实现的效率比数组底 长度可动态扩展,可以存储 各种类型的数据

equals ,等于( =),等等于( ==) ,恒等于 ( ===) 的区别
equals:对象的值
=:赋值
==:比较的是他们的变量值
===:比较值及类型

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值