实例方法和静态方法有什么不一样
1.在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。
而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
2.静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许
访问实例成员变量和实例方法,如果需要调用,则需要先实例化;实例方法则无此限制
3.静态方法是在类中使用staitc修饰的方法,在类定义的时候已经被装载和分配。而非静态方法是
不加static关键字的方法,在类定义时没有占用内存,非静态方法只有在类被实例化成对象时,对象
调用该方法才被分配内存
Java中的异常有哪几类?分别怎么使用
常用的集合类有哪些?List如何排序?
ArrayList和LinkedList的区别
ArrayList
LinkedList
数据结构
动态数组
双向链表
get(index)
O(1)
O(n)
add(E)插入末尾
O(1)
O(1)
add(index,E )
O(n)
O(n)
remove()
O(n)
O(1)
BlockingQueue的使用。(take,poll的区别,put,offer的区别)
入队:
poll():如果没有元素,直接返回null;如果有元素,出队
take():如果队列空了,一直阻塞,直到队列不为空或者线程被中断-->阻塞
出队:
offer(E e):如果队列没满,立即返回true; 如果队列满了,立即返回false
put(E e):如果队列满了,一直阻塞,直到队列不满了或者线程被中断-->阻塞
ClassLoader有什么用
能不能自己写个类叫java.lang.System?如果不行,请说明原因;如果可以,请说明实现思路
通常不可以,但可以采取另类方法达到这个需求。
为了不让我们写System类,类加载采用委托机制,这样可以保证爸爸们优先,爸爸们能找到的类,儿子就没有机会加载。而System类是Bootstrap加载器加载的,就算自己重写,也总是使用Java系统提供的System,自己写的System类根本没有机会得到加载。
但是,我们可以自己定义一个类加载器来达到这个目的,为了避免双亲委托机制,这个类加载器也必须是特殊的。由于系统自带的三个类加载器都加载特定目录下的类,如果我们自己的类加载器放在一个特殊的目录,那么系统的加载器就无法加载,也就是最终还是由我们自己的加载器加载。
==和equals的区别
==是一个比较运算符,基本数据类型比较的是值,引用数据类型比较的是地址值
equals()是一个方法,只能比较引用数据类型。重写前比较的是地址值,重写后比一般是比较对象的属性
hashCode方法的作用
Object类中有哪些方法
HashMap数据结构、扩展策略,如何实现线程安全的HashMap
HashSet与HashMap怎么判断集合元素重复
Java中基础类型字节数
创建一个类的实例都有哪些办法
如何获取一个类的反射
利用反射机制可以获取类对象(也就是我们前面介绍的类对象,获取类对象之后我们便获取了类的模板,可以对类进行一些操作),有以下三种方法:
类名.class()
对象名.getClass()
Class.forName(具体的类名)
java反射可以获取什么
构造方法 getConstructors
成员变量 getFields
Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField("name")方法获取,通过set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值.
获得方法并使用 getMethod
获得该类的所有接口 getInterfaces
Class[] getInterfaces():确定此对象所表示的类或接口实现的接口
返回值:接口的字节码文件对象的数组
final/finally/finalize的区别
LinkingBlockingQueue与ArrayBlockingQueue的区别
Session/Cookine的区别
String/StringBuffer/StringBuilder的区别
Servlet的生命周期
如何用Java分配一段连续的1G的内存空间
Java里面用对象作为Key需要注意些什么? 如何实现hashcode
看如下代码:
返回结果:
这是因为get元素的时候,执行了equals方法和hashCode方法。
new一个新的对象时,地址变了,不能保证hash值和equals结果还是一样。所以取不到对应的value
所以需要重写equals 和hashCode方法 注意这两个方法需要同时重写 重写hashCode 可以保证hash操作
可以找到散列表的同一个位置 重写equals可以保证数据比较value的时候返回true 最终取到对应的value
返回结果:
讲一下常见编码方式
ASCII 码
学过计算机的人都知道 ASCII 码,总共有 128 个,用一个字节的低 7 位表示,0~31 是控制字符如换行回车删除等;32~126 是打印字符,可以通过键盘输入并且能够显示出来。
ISO-8859-1
128 个字符显然是不够用的,于是 ISO 组织在 ASCII 码基础上又制定了一些列标准用来扩展 ASCII 编码,它们是 ISO-8859-1~ISO-8859-15,其中 ISO-8859-1 涵盖了大多数西欧语言字符,所有应用的最广泛。ISO-8859-1 仍然是单字节编码,它总共能表示 256 个字符。
GB2312
它的全称是《信息交换用汉字编码字符集 基本集》,它是双字节编码,总的编码范围是 A1-F7,其中从 A1-A9 是符号区,总共包含 682 个符号,从 B0-F7 是汉字区,包含 6763 个汉字。
GBK
全称叫《汉字内码扩展规范》,是国家技术监督局为 windows95 所制定的新的汉字内码规范,它的出现是为了扩展 GB2312,加入更多的汉字,它的编码范围是 8140~FEFE(去掉 XX7F)总共有 23940 个码位,它能表示 21003 个汉字,它的编码是和 GB2312 兼容的,也就是说用 GB2312 编码的汉字可以用 GBK 来解码,并且不会有乱码。
UTF-16
说到 UTF 必须要提到 Unicode(Universal Code 统一码),ISO 试图想创建一个全新的超语言字典,世界上所有的语言都可以通过这本字典来相互翻译。可想而知这个字典是多么的复杂,关于 Unicode 的详细规范可以参考相应文档。Unicode 是 Java 和 XML 的基础,下面详细介绍 Unicode 在计算机中的存储形式。
UTF-16 具体定义了 Unicode 字符在计算机中存取方法。UTF-16 用两个字节来表示 Unicode 转化格式,这个是定长的表示方法,不论什么字符都可以用两个字节表示,两个字节是 16 个 bit,所以叫 UTF-16。UTF-16 表示字符非常方便,每两个字节表示一个字符,这个在字符串操作时就大大简化了操作,这也是 Java 以 UTF-16 作为内存的字符存储格式的一个很重要的原因
UTF-8
UTF-16 统一采用两个字节表示一个字符,虽然在表示上非常简单方便,但是也有其缺点,有很大一部分字符用一个字节就可以表示的现在要两个字节表示,存储空间放大了一倍,在现在的网络带宽还非常有限的今天,这样会增大网络传输的流量,而且也没必要。而 UTF-8 采用了一种变长技术,每个编码区域有不同的字码长度。不同类型的字符可以是由 1~6 个字节组成
utf-8编码中的中文占几个字节;int型几个字节
utf-8的编码规则:
如果一个字节,最高位为0,表示这是一个ASCII字符(00~7F)
如果一个字节,以11开头,连续的1的个数暗示这个字符的字节数
一个utf8数字占1个字节
一个utf8英文字母占1个字节
少数是汉字每个占用3个字节,多数占用4个字节
说说你对Java注解的理解
java注解:
注解,也叫元数据。一种代码级别的说明,在JDK1.5之后引入的特性,与类、接口、枚举同一层次。可以声明在包、类、字段、方法、局部变量、方法参数等前面,来对这些元素进行说明,注释等。
作用分类:
1)编写文档:通过代码里的标识的元数据生成文档【生成文档doc文档】
2)代码分析:通过代码里的标识的元数据对代码进行分析【使用反射】
3)编译检查:通过代码里的标识的元数据让编译器能过实现基本的编译检查【Override】
元注解:
java提供了四个元注解,所谓元注解就是负责注解其他注解。
@Target :规定注解所修饰的对象范围。
1)ElementType.CONSTRUCTIR; 构造器声明
2)ElementType.FIELD; 成员变量,对象,属性(包括enum实例)
3)ElementType.LOCAL_VARIABLE; 局部变量声明
4)ElementType.METHOD ; 方法声明
5)ElementType.PACKAGE; 包声明
6)ElementType.PARAMETER;参数声明
7)ElementType.TYPE; 类、接口(包括注解类型)或enum声明
@Retention : 表示注解的生命周期
1)RetentionPolicy.SOUREC: 在源文件中有效
2)RetentionPolicy.CLASS; 在class文件中有效
3)RetentionPolicy.RUNTIME;在运行时有效
@Inherited : 标记注解,主要说明了一种继承性,意思是子类可以继承父类中的该注解(注意:只有当被贴上@Inherited标签的注解被用在类上的时候子类才能获得这个注解)。
@Documented : 用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化
ThreadLocal原理
首先在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。
初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals
为什么ThreadLocalMap里Entry为何声明为WeakReference
WeakReference是Java语言规范中为了区别直接的对象引用(程序中通过构造函数声明出来的对象引用)而定义的另外一种引用关系。
WeakReference标志性的特点是:reference实例不会影响到被应用对象的GC回收行为(即只要对象被除WeakReference对象之外所有的对象解除引用后,该对象便可以被GC回收),只不过在被对象回收之后,reference实例想获得被应用的对象时程序会返回null
WeakReference对应用的对象users是弱引用,不会影响到users的GC行为。
如果是强引用的话,在线程运行过程中,我们不再使用users了,将users置为null,但users在线程的ThreadLocalMap里还有引用,导致其无法被GC回收(当然,可以等到线程运行结束后,整个Map都会被回收,但很多线程要运行很久,如果等到线程结束,便会一直占着内存空间)。
而Entry声明为WeakReference,users置为null后,线程的threadLocalMap就不算强引用了,users就可以被GC回收了。map的后续操作中,也会逐渐把对应的"stale entry"清理出去,避免内存泄漏
所以,我们在使用完ThreadLocal变量时,尽量用threadLocal.remove()来清除,避免threadLocal=null的操作。
前者remove()会同时清除掉线程threadLocalMap里的entry,算是彻底清除
而后者虽然释放掉了threadLocal,但线程threadLocalMap里还有其"stale entry",后续还需要处理