一、成员变量和局部变量
局部变量是定义在方法体内部的变量,其作用域在方法块内部有效。
局部变量在使用时,必须先初始化才能使用,否则不能顺理通过编译;
成员变量是定义的变了里那个,即属性,其作用域整个类中有效;
成员变量可以不指定初始值,系统有默认值:除了八种基本数据类型,
其他的引用类型都是null;
Byte、Short、int的初始值为0;long的初始值为0L;boolean为false;
float的为0.0F;double的为0.0d;char为‘/u0000’;
被final修饰且没有被static修饰的成员变量必须显式赋初始值;
成员变量和局部变量的区别:
1、 public、protect、private、static可以修饰成员变量,但不能修饰局部变量;两者都可以用final修饰;
2、 成员变量存储在堆内存中,局部变量存储在栈内存中
3、 作用域不同,局部变量作用域在方法块内部,成员变量作用域整个类
4、 成员变量可以不设置默认值,局部变量必须设置默认值。
二、overload和override的区别
Overload(重载):
1、是同一个类中含有多个方法名称相同但参数列表(参数个数、类型、顺序)不相同的方法。
2、这些方法可能是当前类直接声明的,也可能是从父类中继承过来的可见方法。
Override(重写)
1、重写必须是子类继承父类后,子类重新声明了从父类中继承的可见(visible)方法,
2、此时,如果子类中重新声明的方法与父类中的方法 名称相同、参数列表完全相同、返回类型也一致,就说子类重写了父类中的同名方法。
相同点:都要求方法名称相同;
不同点: 1、 重载要求本类中有同名不同那个参的方法;重写必须发生在子类和父类之间; 2、 重载 要求同名方法的参数列表一定不相同;重写要求子类和父类的同名方法 的参数列表完全相同; 3、 重载对返回类型么有要求;而 重写 ( override ) 要求 被重写后的方法的返回 类型 必须跟 父类中相应方法保持一致 ( 如果是返回基本类型,则要求完全相同 ) 4、 重载( overload ) 对方法的 权限修饰符 没有要求,而 重写 ( override ) 要求 被重写后的方法的 权限修饰符 的范围不能缩小
注意:
子类不能重写父类的 静态方法,如果子类重新声明了父类中同名的静态方法,
则说 子类 隐藏 了 父类中的同名静态方法。
三、int 和 Integer 有什么区别?
int 是基本类型32位长度的整数
Integer 是类类型,是int的封装类
int和Integer之间可以通过自动装箱 自动拆箱 互相转换
String 和StringBuffer的区别?
String是immutable的,其内容一旦创建好之后,就不可以发生改变。 StringBuffer 是可以变长的,内容也可以发生改变 改变的原理是StringBuffer内部采用了字符数组存放数据,在需要增加长度的时候,创建新的数组,并且把原来的数据复制到新的数组这样的办法来实现。
说出ArrayList,Vector, LinkedList的存储性能和特性。
先说ArrayList和Vector
两者都继承了抽象类AbstractList,但是Vector是线程安全的,而ArrayList是非线程安全的
再说ArrayList和LinkedList的区别
ArrayList 是数组结构,所以定位很快,但是插入和删除很慢
LinkedList 是双向链表结构,所以插入和删除很快,但是定位很慢
Collection 和 Collections的区别
首先不要说成了一个是单数,一个是复数。。。
Collection是接口,是List和Set的父接口
Collections是工具类,提供了排序,混淆等等很多实用方法
HashMap和Hashtable的区别
HashMap和Hashtable都实现了Map接口,都是键值对保存数据的方式
区别1:
HashMap可以存放 null
Hashtable不能存放null
区别2:
HashMap不是线程安全的类
Hashtable是线程安全的类
final, finally, finalize的区别
final
- final修饰类,方法,基本类型变量,引用的时候分别有不同的意思
- 修饰类 表示该类不能被继承
- 修饰方法 表示该方法不能被重写
- 修饰基本类型变量 表示该变量只能被赋值一次
- 修饰引用 表示该引用只有一次指向对象的机会
finally
- finally 是用于异常处理的场面,无论是否有异常抛出,都会执行
finalize
- finalize是Object的方法,所有类都继承了该方法。 当一个对象满足垃圾回收的条件,并且被回收的时候,其finalize()方法就会被调用
Error和Exception有什么区别
Error和Exception都实现了Throwable接口
Error指的是JVM层面的错误,比如内存不足OutOfMemoryError
Exception 指的是代码逻辑的异常,比如下标越界OutOfIndexException
abstract class和interface区别
使用方式:
抽象类只能够通过继承被使用
接口必须通过实现被使用
实现方法:
抽象类不仅可以提供抽象方法,也可以提供实现方法
接口只能提供抽象方法,不能提供实现方法。 但是在JAVA8版本开始,接口可以提供实现方法了,前提是要在方法前加一个default修饰符
heap和stack区别
heap:堆
stack:栈
存放的内容不一样:
heap: 是存放对象的
stack: 是存放基本类型(int, float, boolean 等等)、引用(对象地址)、方法调用
存取方式不一样:
heap: 是自动增加大小的,所以不需要指定大小,但是存取相对较慢
stack: 是固定大小的,并且是FILO 先入后出的顺序,并且存取速度比较快
数组与String
数组获取长度的手段是 .length 属性
String获取长度的手段是 length()方法
集合获取长度的手段是 size()方法
文件获取长度的手段是 length()方法
集合类
常见的集合
ArrayList,LinkedList,HashSet,HashMap,TreeSet 等等
常见方法:
size()
add()
remove()
等等
关键字:throws,throw,try,catch,finally
throws 用在方法声明上面,表示该方法有可能抛出某个异常
throw 抛出一个指定的异常
try catch 在try中有可能会抛出某个异常,一旦某个异常抛出后,就会在catch中进行捕捉,他俩一般说来都是成对出现的。
finally: 表示无论是否捕捉住异常,都会执行
java中会存在内存泄漏吗
因为Java是自动进行垃圾回收管理的,所以不存在 C语言中同等概念的内存泄漏,但是存在Java特色的内存泄漏
当某些对象不被使用,但是又有非直接引用指向的时候,那么就不满足垃圾回收的条件,而形成内存泄漏。
比如代码中的例子,每个Object创建的时候,有一个引用o指向,接着就被放进了集合al中。 下一个Object创建的时候,上一个Object就没有引用指向了。
java序列化
序列化指的是把一个Java对象,通过某种介质进行传输,比如Socket输入输出流,或者保存在一个文件里
实现java序列化的手段是让该类实现接口 Serializable,这个接口是一个标识性接口,没有任何方法,仅仅用于表示该类可以序列化。
多线程
多线程实现的三种方法
通常来讲,Java 创建一个线程有三种方式
- 继承一个Thread类
- 实现Runnable接口
- 匿名内部类
线程安全
线程安全,死锁
多线程的同步问题指的是多个线程同时修改一个数据的时候,可能导致的问题
多线程的问题,又叫Concurrency 问题
**synchronized 同步对象概念 **
Object someObject =new Object();
synchronized (someObject){
//此处的代码只有占有了someObject后才可以执行
}
synchronized表示当前线程,独占 对象 someObject
当前线程独占 了对象someObject,如果有其他线程试图占有对象someObject,就会等待,直到当前线程释放对someObject的占用。
someObject 又叫同步对象,所有的对象,都可以作为同步对象
为了达到同步的效果,必须使用同一个同步对象
释放同步对象的方式: synchronized 块自然结束,或者有异常抛出
package multiplethread;
import java.awt.GradientPaint;
import charactor.Hero;
public class TestThread {
public static void main(String[] args) {
final Object someObject = new Object();
final Hero gareen = new Hero();
gareen.name = "盖伦";
gareen.hp = 10000;
int n = 10000;
Thread[] addThreads = new Thread[n];
Thread[] reduceThreads = new Thread[n];
for (int i = 0; i < n; i++) {
Thread t = new Thread(){
public void run(){
//任何线程要修改hp的值,必须先占用someObject
synchronized (someObject) {
gareen.recover();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
addThreads[i] = t;
}
for (int i = 0; i < n; i++) {
Thread t = new Thread(){
public void run(){
//任何线程要修改hp的值,必须先占用someObject
synchronized (someObject) {
gareen.hurt();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
reduceThreads[i] = t;
}
for (Thread t : addThreads) {
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (Thread t : reduceThreads) {
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.printf("%d个增加线程和%d个减少线程结束后%n盖伦的血量是 %.0f%n", n,n,gareen.hp);
}
}
sleep() 和 wait() 有什么区别
首先sleep和wait之间没有任何关系
sleep 是Thread类的方法,指的是当前线程暂停。
wait 是Object类的方法, 指的占用当前对象的线程临时释放对当前对象的占用,以使得其他线程有机会占用当前对象。 所以调用wait方法一定是在synchronized 中进行
说出数据连接池的工作机制是什么?
数据库连接池原理:
因为创建连接和关闭连接的行为是非常耗时的,会显著降低软件的性能表现。解决办法就是先创建n条数据库连接Connection,循环使用,但是不进行关闭,这样再执行SQL语句,就不需要额外创建连接了,直接使用现成的连接就可以了,从而节约了创建连接和关闭连接的时间开销。
简述synchronized和java.util.concurrent.locks.Lock的异同 ?
-
Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现,Lock是代码层面的实现。
-
Lock可以选择性的获取锁,如果一段时间获取不到,可以放弃。synchronized不行,会一根筋一直获取下去。 借助Lock的这个特性,就能够规避死锁,synchronized必须通过谨慎和良好的设计,才能减少死锁的发生。
-
synchronized在发生异常和同步块结束的时候,会自动释放锁。而Lock必须手动释放, 所以如果忘记了释放锁,一样会造成死锁。
多线程防止死锁,synchronized 发生异常或同步结束会自动释放锁,而lock需要手动释放锁。
Class.forName的作用?为什么要用?
Class.forName常见的场景是在数据库驱动初始化的时候调用。
Class.forName本身的意义是加载类到JVM中。 一旦一个类被加载到JVM中,它的静态属性就会被初始化,在初始化的过程中就会执行相关代码,从而达到"加载驱动的效果"
多线程应用场景
多线程最多的场景:web服务器本身;各种专用服务器(如游戏服务器);多线程的常见应用场景:
1、后台任务,例如:定时向大量(100w以上)的用户发送邮件;
2、异步处理,例如:发微博、记录日志等;
3、分布式计算
来源:oschina
链接:https://my.oschina.net/corwien/blog/4316020