什么是JDK,JRE,JVM?
JRE:java运行环境,里面包括JVM
JDK:java开发工具,里面包含了JRE
JVM:java虚拟机
什么是javaSE,javaEE,javaME?
javaEE:用来开发web应用的
javaSE:主要用于开发桌面应用程序
javaME:主要用于开发移动设备和嵌入式设备
JVM内存模型
线程私有区域:
程序计数器:用来执行虚拟机字节码指令的(看我们java代码写到哪一行那个序号) 本地方法栈:存放 Native方法 虚拟机栈:里面存着栈帧,一个一个栈帧就是我们运行时的方法;也存放局部变量,引用数据类型地址等
线程共享区域:
堆区:几乎所有的对象和数组都存放在堆区 方法区:存放类信息,静态变量,还有常量
什么是面向对象?什么是面向过程?
面向对象就是一种思想,让我们站在对象的角度思考问题,强调的是我该让谁去做
面向过程就是站在过程的角度思考问题,强调的是我该怎么去做(即功能的执行过程)
面向对象的三大特性是什么?
封装:把客观事物封装成抽象的类,并且把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏(将对象的字段和方法存放在一个类中)
继承:一个类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类,子类拥有父类的所有属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用
多态:一个对象有多种形态,同一数据引用类型的对象( Animal animal ),引用的实例不同( new Dog / new Cat ),调用的方法( say() )产生不同的结果
什么是javabean?
javabean是一种规范它规定了这个类必须是public修饰的
而且属性必须私有化
每一个属性都要提供对应的get和set方法
类中必须要有一个无参构造器
有哪8大基本数据类型,他们字节分别是多少?
String是引用数据类型,不是8大基本数据类型
1.存储位置不同:
基本数据类型的内容是存储在栈中的;
引用数据类型,其具体内容都是存放在堆中的,而栈中存放的是其具体内容所在内存的地址
2.传递方式不同:基本数据类型是值传递,引用数据类型是按引用数据传递的
对象的四种引用级别?
强引用:如果一个对象具有强引用,当内存空间不足,Java虚拟机宁愿抛出错误,使程序异常终止,垃圾回收器绝不会回收它来解决内存不足问题
软引用:如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存
弱引用:在垃圾回收器线程扫描的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存
虚引用:和没有任何引用一样,在任何时候都可能被垃圾回收;虚引用主要用来跟踪对象被垃圾回收的活动,必须和引用队列联合使用
字符串常量池的理解?
JVM为了提高性能和减少内存开销,为字符串开辟一个字符串常量池,类似于缓存区
创建字符串常量时,首先检查字符串常量池是否存在该字符串
存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中
成员变量和局部变量有什么区别?
成员变量只会存在于类中,方法外;除了成员变量其他的都是局部变量,比如方法形参;
成员变量可以使用各种访问修饰符:public、protected、private...,局部变量只能由final修饰
优先级不同:局部变量的优先级高于成员变量(就近原则)
构造器 Constructor 是否可被 override?
Constructor 不能被 override(重写),但是可以 overload(重载),所以你可以看到一个类中有多个构造函数的情况。
重载和重写的区别
重载
发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同
重写
重写是子类对父类的允许访问的方法的实现过程进行重新编写,发生在子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。另外,如果父类方法访问修饰符为 private 则子类就不能重写该方法。也就是说方法提供的行为改变,而方法的外貌并没有改变。
Java 面向对象编程三大特性
封装,继承,多态
String 为什么是不可变的?
String 类中使用 final 关键字修饰字符数组来保存字符串,private final char[] value
,所以 String 对象是不可变的。
String、StringBuffer 和 StringBuilder 的区别是什么?
可变性
String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[]
,所以 String 对象是不可变的。而 StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串char[]value
但是没有用 final 关键字修饰,所以这两种对象都是可变的。
线程安全性
StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
性能
每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
对于三者使用的总结:
操作少量的数据: 适用 String
单线程操作字符串缓冲区下操作大量数据: 适用 StringBuilder
多线程操作字符串缓冲区下操作大量数据: 适用 StringBuffer
请列出String的常用方法
获取长度:length()
根据位置获取位置上某个字符:charAt(int index)
根据字符获取该字符在字符串中位置:indexOf(int ch):返回的是ch在字符串中第一次出现的位置
判断字符串中是否包含某一个子串: contains(str):
判断字符串中是否有内容:isEmpty();
判断字符串是否以指定内容开头/结尾: startsWith(str);/endsWith(str);
忽略大小写判断内容是否相同:equalsIgnoreCase();
切割: split(regex);
截取字符串中的一部分: substring(begin);
字符串转成大写或则小写:toUpperCase();//toLowerCase();
自动装箱与拆箱
装箱:将基本类型用它们对应的引用类型包装起来;
拆箱:将包装类型转换为基本数据类型;
数据库索引?
数据库三范式?
第一范式:数据库的表中的每一列只能存储一个值
第二范式:表中必须要有一个主键
第三范式:当一张表需要依赖到另外一张表的信息时,只应该储存另一张表的主键信息,不应该存储非主键信息
sql的常见优化策略
1.查询时避免全局搜索(也就是尽量不使用*)
2.尽量使用批量新增而不使用普通新增
3.尽量多使用连表查询代替子查询
4.避免使用+-*/=这些算数运算符
5.少用in,not in,null;
6.避免频繁的删除表和新增表
7.使用exits 代替 in
SQL中时间格式的处理方式
YEAR(时间的列名):显示出该列的年份
DATE_FORMAT(列名,'%Y-%m-%d %H:%i:%s'):转格式为xxxx(年)-xx(月)-xx(日) xx(时):xx(分):xx(秒)
类的加载过程?(了解就行)
JVM把class文件加载到内存,并对数据进行校验、准备、解析、初始化,最终形成JVM可以直接使用的Java类型的过程
接口和抽象类的区别是什么?
1.第一点. 接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它的类 2.第二点. 接口可以多继承,抽象类不行 3.第三点. 接口定义方法,不能实现,而抽象类可以实现部分方法 4.第四点. 接口中基本数据类型为static 而抽类象不是的
接口的方法默认是 public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),而抽象类可以有非抽象的方法。
接口中除了 static、final 变量,不能有其他变量,而抽象类中则不一定。
一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过 extends 关键字扩展多个接口。
接口方法默认修饰符是 public,抽象方法可以有 public、protected 和 default 这些修饰符(抽象方法就是为了被重写所以不能使用 private 关键字修饰!)。
构造方法有哪些特性?
名字与类名相同
没有返回值,但不能用 void 声明构造函数
生成类的对象时自动执行,无需调用
在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
帮助子类做初始化工作
== 与 equals区别
== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?
是为了提高效率,采取重写hashcode方法,先进行hashcode比较,如果不同,那么就没必要在进行equals的比较了,这样就大大减少了equals比较的次数,这对比需要比较的数量很大的效率提高是很明显的;
并行: 同一时间点执行多个任务
并发:同一时间段中执行多个任务
线程和进程的区别?
线程是进程中最小的执行单位,一个进程中可以运行多个线程,多个线程可共享进程的数据;
进程是指一个内存中运行的应用程序
线程的创建的两种方式?
继承Thread类
实现Runnable 接口
实现callable接口
利用线程池来创建线程
什么是多线程?
多线程指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务
自定义注解要注意什么?
@target 声明注解贴到哪个地方
@Retention注解在什么时候有用[source,class,runtime,一般自定义注解都是runtime]
(这两个也叫元注解[注解的注解])
线程有哪些基本状态,并描述每种状态?
java中,每个线程都需经历新生、就绪、运行、阻塞和死亡五种状态,线程从新生到死亡的状态变化称为生命周期 用new运算符和Thread类或其子类建立一个线程对象后,该线程就处于新生状态 新生--->就绪:通过调用start()方法 就绪--->运行:处于就绪状态的线程一旦得到CPU,就进入运行状态并自动调用自己的run()方法 运行--->阻塞:处于运行状态的线程,执行sleep()方法,或等待I/O设备资源,让出CPU并暂时中止自己运行,进入阻塞状态 阻塞--->就绪:睡眠时间已到,或等待的I/O设备空闲下来,线程便进入就绪状态,重新到就绪队列中等待CPU。当再次获得CPU时,便从原来中止位置开始继续运行。 运行--->线程任务完成
final 关键字修饰这三个地方:变量、方法、类,会有什么作用
如果修饰类,则该类无法被继承。 如果修饰方法,改方法无法被重写。 如果修饰的是基本数据类型变量,则该无法被赋予其他值
对于一个 final 变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
当用 final 修饰一个类时,表明这个类不能被继承。final 类中的所有成员方法都会被隐式地指定为 final 方法。
使用 final 方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的 Java 实现版本中,会将 final 方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的 Java 版本已经不需要使用 final 方法进行这些优化了)。类中所有的 private 方法都隐式地指定为 final。
Java 序列化中如果有些字段不想进行序列化,怎么办?
对于不想进行序列化的变量,使用 transient 关键字修饰。
transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法。
获取用键盘输入常用的两种方法
方法 1:通过 Scanner
Scanner input = new Scanner(System.in); String s = input.nextLine(); input.close();
方法 2:通过 BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String s = input.readLine();
既然有了字节流,为什么还要有字符流?
问题本质想问:不管是文件读写还是网络发送接收,信息的最小存储单元都是字节,那为什么 I/O 流操作要分为字节流操作和字符流操作呢?
回答:字符流是由 Java 虚拟机将字节转换得到的,问题就出在这个过程还算是非常耗时,并且,如果我们不知道编码类型就很容易出现乱码问题。所以, I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。
1. 字节输出流是直接把字节数据写出到磁盘或其他设备上,而字符输出流会先把字符输出流按一定的编码规则进行编码成二进制的字节输出流再写出到磁盘或其他设备上。 2. 字节输入流每次读取一个字节数据到内存(也可以使用缓冲区一次读取多个),而字符输入流是每次读取多个字节的数据到内存中,然后对读取的字节数据按照一定的编码规则进行解码,然后形成文本数据。 3. 总的来说,系统到磁盘或者其他设备上的数据,从其他数据读取到内存中时,都是字节数据,只是java封装了一层字节到字符或者字符到字节的工序。 4. 字节流适用于任何形式的数据;而字符流只适用于文本数据,不能用字符流来传输诸如图片、语言、视频等二进制数据。但是处理文本数据字符流要比字节流方便许多。 5. 使用字符输出流时一定要记得使用flush方法或者close方法把数据强制刷出到磁盘或其他设备,因为字符流会存在缓冲区,除非缓冲区满了才会自动刷出到磁盘或者其他设备中。使用字节流的话如果带有或者使用缓冲区的话,就也要强制刷出到磁盘或者其他设备中。
什么是IO?
input输入/output输出;
在计算机中对于程序来说,读取一个数据属于输入操作,写出一个数据属于输出操作
Java程序的读写本质是在做什么?
读:将磁盘中的数据读取到内存中
写:将内存中的数据保存到磁盘中
IO模型 BIO/NIO/AIO(面试扩展题)
BIO: 同步阻塞IO模型:在两次拷贝数据期间(一次是网卡拷贝到内存当中,第二次是从内存拷贝到应用程序当中),该线程会全程堵塞
NIO:同步非阻塞IO模型:线程请求获取数据后,如果没有数据,立马返回应用程序,可以继续做自己的事情,当内核数据准备好以后,才从内核中拷贝数据到应用程序
AIO:异步IO模型 :事件机制驱动的异步io模型,首先向内核注册一个需要读数据的事件,当操作内核将数据准备并拷贝到主内存后,通知应用程序来读取数据
BIO:同步阻塞io模型,数据的读取写入必须在一个线程内等待其完成。 AIO:异步非阻塞io模型,询问一次数据之后,系统会通知对应的线程来处理。 NIO:多路复用,同步非阻塞io,但也支持阻塞模式,会轮询数据,会一直去询问数据是否准备好了,然后才进行下一步操作。
描述深拷贝和浅拷贝
浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
说说&和&&的区别。
&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。
&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式。
&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0x31 & 0x0f的结果为0x01。
final, finally, finalize的区别
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。内部类要访问局部变量,局部变量必须定义成final类型。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。但是JVM不保证此方法总被调用