、、
A 选项:Interrupt 确实会导致线程中断,但是既然捕获到异常就代表线程不会中断和停止
B 选项:线程调用 wait()方法,释放了锁,会强制导致当前正在执行的线程中断,需要 notify()或 notifyall()来“唤醒“
C 选项:当线程创建一个新的线程时,CPU 时间片不会剥夺当前线程运行的“权利”
D 选项:当高优先级线程进入就绪状态,也需要等待当前线程的运行结束才可以继续运行,此时当前线程处于运行中 RUBBABLE 状态中的 READY 就绪态
、、
结论:
try块中抛出异常,try、catch和finally中都有return语句,返回值是finally中的return。
return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂存在栈里面,等待finally执行后再返回)
、、
、、
A:静态成员变量或静态代码块>main方法>非静态成员变量或非静态代码块>构造方法
B:think in java中提到构造器本身并没有任何返回值。
C: 构造方法的主要作用是完成对类的对象的初始化工作。
D: 一般在创建(new)新对象时,系统会自动调用构造方法。
、、
饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,而不是开始初始化 ,评论区很多人别误人子弟。注意:单例是已经存在,而不是才开始初始化单例。你们说的那是懒汉模式。懒汉模式,只有当调用getInstance的时候,才回去初始化这个单例。
单例模式:某一个类将自己的构造方法定义成private,那么外部的程序就不能通过new的方法来实例化这个类的对象,这样是否实例化对象的责任就变成类本身自己的责任,而不是别人(其他程序)的责任。保证一个雷仅有一个实例,并且提供一个访问它的全局访问点。
、、
yield()把正在运行的线程转为就绪态,放在就绪队列里面,如果争取到了CPU资源立马可以执行
、、
扩展:String对象怎么就不可变?
底层char[]数组有final修饰,意味着这个数组不能扩容等,来达到存更多的字符
char[]数组是私有的,程序员无法直接操作这个char[]数组,而且String没有提供这样的方法,来修改char[]数组的元素的值。
String提供的所有的方法,对字符串的修改都是给你返回一个新的字符串对象。
、、
这个改变的只是栈变量的引用地址不是堆里面的对象内容。
在Java内存模型(Java Memory Model,JMM)中,局部变量一般存储在线程的栈帧(Stack Frame)中。每个线程在调用方法时,都会创建一个栈帧,用于存储方法的参数、局部变量和其他相关信息。当方法执行完毕时,栈帧会被销毁,局部变量的内存空间也会被释放。
在栈帧中,局部变量的存储通常是基于栈(Stack)的数据结构,它们的生命周期与方法的执行周期密切相关。因为局部变量存储在栈中,所以它们的访问速度比堆(Heap)中的对象要快,但是也存在一些限制,比如局部变量的作用域只在方法内部有效,方法执行完毕后就无法访问了。
1、
for(foo('A'); foo('B') && (i < 2); foo('C')) { ... }
: 这是一个 for
循环。循环的三个部分
分别是初始化部分、循环条件部分和迭代部分。
2、
3、
d:a equal s
程序会把s封装成一个Long类型,由于Square没有重写Object的equals方法, 所以调用的是Object类的equals方法,源码如下。因此这里的equals是比较地址;
、、
java在编译Integer i2 = 128的时候,被翻译成-> Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存
Java重写有如下标准:
-
参数列表必须与被重写方法的相同。
-
重写方法不能限制比被重写方法更严格的访问级别
-
重写方法不能抛出新的异常或者比被重写方法声明的检查异常更广的检查异常
-
返回类型必须与被重写方法的返回类型相同。仅当返回值为类类型时,重写的方法才可以修改返回值类型,且必须是父类方法返回值的子类。
1. HashMap,TreeMap 未进行同步考虑,是线程不安全的。 2. HashTable 和 ConcurrentHashMap 都是线程安全的。区别在于他们对加锁的范围不同,HashTable 对整张Hash表进行加锁,而ConcurrentHashMap将Hash表分为16桶(segment),每次只对需要的桶进行加锁。 3. Collections 类提供了synchronizedXxx()方法,可以将指定的集合包装成线程同步的集合。比如, List list = Collections.synchronizedList(new ArrayList()); Set set = Collections.synchronizedSet(new HashSet());
、、
public为类加载器提供入口,然后找到public类中的main方法开始执行。如果存在多个public类,程序将不知道该从哪里执行。内部类可以是public的,因为内部类是作为外部类的成员存在的。
、、
字符串常量池实现的前提条件就是Java中String对象是不可变的,这样可以安全保证多个变量共享同一个对象。如果Java中的String对象可变的话,一个引用操作改变了对象的值,那么其他的变量也会受到影响,显然这样是不合理的。
、、
String str1 = "hello";
这里的str1指的是方法区中的字符串常量池中的“hello”,编译时期就知道的;
String str2 = "he" + new String("llo");
这里的str2必须在运行时才知道str2是什么,所以它是指向的是堆里定义的字符串“hello”,所以这两个引用是不一样的。
如果用str1.equal(str2),那么返回的是true;因为String类重写了equals()方法。
编译器没那么智能,它不知道"he" + new String("llo")的内容是什么,所以才不敢贸然把"hello"这个对象的引用赋给str2.
如果语句改为:"he"+"llo"这样就是true了。
new String("zz")实际上创建了2个String对象,就是使用“zz”通过双引号创建的(在字符串常量池),另一个是通过new创建的(在堆里)。只不过他们的创建的时期不同,一个是编译期,一个是运行期。
String s = "a"+"b"+"c";
语句中,“a”,"b", "c"都是常量,编译时就直接存储他们的字面值,而不是他们的引用,在编译时就直接将它们连接的结果提取出来变成"abc"了。
、、
如果没有修饰符,默认是default,仅在当前类和同一个包下可以访问。
接口实现类相当于子类,
子类重写父类方法,三同一小一大原则:
三同:方法名相同,形参列表相同,返回值类型相同;C、D车错误
一小:子类方法声明抛出的异常比父类方法声明抛出的异常更小或者相等
一大:子类方法的访问修饰符应该比父类方法更大或者相等;本题B选项就不符合,default < public。
、、
HashMap的底层是哈希表,而Java中哈希表是由数组+链表实现的,每一个数组的节点称之为bucket桶,当桶中由多个元素就以链表的方法进行存储,当添加元素时,通过key的hash算法得出hash值,然后通过hash值映射出存在哪个桶中,如果桶中没有有元素,就添加成功,如果有元素那就代表散列冲突,比较已存在的元素和新插入的元素的hash值是否有相同,如果没有相同的则添加成功(情况1),如果某个元素的hash值和新的元素hash值相同的,则调用key的equals方法继续进行比较,为true则新的值覆盖掉旧的值,为false添加成功(情况2),
对于情况1 和情况2,在jdk1.7是将新的元素添加到原来的头节点,jdk1.8是添加到链表后面,jdk1.8做了一个优化,因为如果链表的长度太长遍历查找复杂度为O(n),所以引入了红黑树,当桶中的元素>8并且数组长度>64就转为红黑树,复杂度为O(logn)
、、
String和StringBuffer和StringBuilder。
String对象一旦创建,其值是不能修改的,如果要修改,会重新开辟内存空间来存储修改之后的对象;而StringBuffer和StringBuilder对象的值是可以被修改的;
StringBuffer几乎所有的方法都使用synchronized实现了同步,线程比较安全,在多线程系统中可以保证数据同步,但是效率比较低;而StringBuilder 没有实现同步,线程不安全,在多线程系统中不能使用 StringBuilder,但是效率比较高。
如果我们在实际开发过程中需要对字符串进行频繁的修改,不要使用String,否则会造成内存空间的浪费;当需要考虑线程安全的场景下使用 StringBuffer,如果不需要考虑线程安全,追求效率的场景下可以使用 StringBuilder。
、、
通过阅读源码可以知道,string与stringbuffer都是通过字符数组实现的。
其中string的字符数组是final修饰的,所以字符数组不可以修改。
stringbuffer的字符数组没有final修饰,所以字符数组可以修改。
string与stringbuffer都是final修饰,只是限制他们所存储的引用地址不可修改。
至于地址所指内容能不能修改,则需要看字符数组可不可以修改。
、、
HTTP是“无状态”协议:客户程序每次读取 Web 页面,都打开到 Web 服务器的单独的连接,并且,服务器也不自动维护客户的上下文信息。即使那些支持持续性 HTTP 连接的服务器,尽管多个客户请求连续发生且间隔很短时它们会保持 socket 打开,但是,它们也没有提供维护上下文信息的内建支持。上下文的缺失引起许多困难。例如,在线商店的客户向他们的购物车中加入商品时,服务器如何知道购物车中己有何种物品呢?类似地,在客户决定结账时,服务器如何能确定之前创建的购物车中哪个属于此客户呢?这些问题虽然看起来十分简单,但是由于 HTTP 的不足,解答它们却异常复杂困难。对于这个问题,存在 3 种典型的解决方案:
Cookie(结合session使用)
可以使用 cookie 存储购物会话的 ID;在后续连接中,取出当前的会话 ID,并使用这个 ID 从服务器上的查找表(lookup table)中提取出会话的相关信息。 以这种方式使用 cookie 是一种绝佳的解决方案,也是在处理会话时最常使用的方式。但是,sevlet 中最好有一种高级的 API 来处理所有这些任务,以及下面这些冗长乏味的任务:从众多的其他cookie中(毕竟可能会存在许多cookie)提取出存储会话标识符的 cookie;确定空闲会话什么时候过期,并回收它们;将散列表与每个请求关联起来;生成惟一的会话标识符。
URL 重写
采用这种方式时,客户程序在每个URL的尾部添加一些额外数据。这些数据标识当前的会话,服务器将这个标识符与它存储的用户相关数据关联起来。 URL重写是比较不错的会话跟踪解决方案,即使浏览器不支持 cookie 或在用户禁用 cookie 的情况下,这种方案也能够工作。URL 重写具有 cookie 所具有的同样缺点,也就是说,服务器端程序要做许多简单但是冗长乏味的处理任务。即使有高层的 API 可以处理大部分的细节,仍须十分小心每个引用你的站点的 URL ,以及那些返回给用户的 URL。即使通过间接手段,比如服务器重定向中的 Location 字段,都要添加额外的信息。这种限制意味着,在你的站点上不能有任何静态 HTML 页面(至少静态页面中不能有任何链接到站点动态页面的链接)。因此,每个页面都必须使用 servlet 或 JSP 动态生成。即使所有的页面都动态生成,如果用户离开了会话并通过书签或链接再次回来,会话的信息也会丢失,因为存储下来的链接含有错误的标识信息。
隐藏的表单域
HTML 表单中可以含有如下的条目:<input type="hidden" name="session" value="a1234">
这个条目的意思是:在提交表单时,要将指定的名称和值自动包括在 GET 或 POST 数据中。这个隐藏域可以用来存储有关会话的信息,但它的主要缺点是:仅当每个页面都是由表单提交而动态生成时,才能使用这种方法。单击常规的超文本链接并不产生表单提交,因此隐藏的表单域不能支持通常的会话跟踪,只能用于一系列特定的操作中,比如在线商店的结账过程。
、、
子类的构造方法总是先调用父类的构造方法,如果子类的构造方法没有明显地指明使用父类的哪个构造方法,子类就调用父类不带参数的构造方法。
而父类没有无参的构造函数,所以子类需要在自己的构造函数中显示的调用父类的构造函数。
、、
1.父类new直接执行构造方法; 2.子类new,先执行父类的构造方法,再执行自己的构造方法
、、
子由父生,执行顺序为:
父类的静态代码块>子类的静态代码块>父类的构造代码块>父类的构造函数>子类的构造代码块>子类的构造函数
1.静态代码块 2.构造代码块3.构造方法的执行顺序是1>2>3;明白他们是干嘛的就理解了。
1.静态代码块:是在类的加载过程的第三步初始化的时候进行的,主要目的是给类变量赋予初始值。
2.构造代码块:是独立的,必须依附载体才能运行,Java会把构造代码块放到每种构造方法的前面,用于实例化一些共有的实例变量,减少代码量。
3.构造方法:用于实例化变量。
1是类级别的,2、3是实例级别的,自然1要优先23.
、、
ABDC。只要是被子类重写的方法,不被super调用都是调用子类方法。
1.多态中非静态方法使用规则 编译看左边,运行看右边。
2.成员变量:编译看左边(父类),运行看左边(父类)
3.多态中静态方法使用规则、编译看左边,运行看左边、只有覆盖没有重写、
把父类以及子类里的成员变量和成员方法随意删掉来验证编译看左边(删除父类的成员变量和成员方法都会报错)、运行看右边。