Java(2)

● 请你说一下Java里integer和int的区别,以及如何比较相等

参考回答:
Integer和int的区别:
1、integer是int的包装类,int是Java的一种基本数据结构

2、integer变量必须实例化后才能使用,int变量不需要

3、integer实际是对象的引用,int是直接存储数据值

4、integer的默认值是null,int的默认值是0

如何比较相等,首先要明白equals和==的区别

Equals通常用来比较两个对象的内容是否相等,
==用来比较两个对象的地址是否相等,
通常会认为两个对象的内容相等时,则两个对象相等,equals返回true。对象内容不同,则返回false。

所以可以总结为两种情况

1、类未复写equals方法,则使用equals方法比较两个对象时,相当于==比较,即两个对象的地址是否相等。地址相等,返回true,地址不相等,返回false。

2、类复写equals方法,比较两个对象时,则走复写之后的判断方式。通常,我们会将equals复写成:当两个对象内容相同时,则equals返回true,内容不同时,返回false。

● 请你介绍下Java学习情况,学习一门新的语言需要多快

参考回答:
如实回答即可,体现出一个学习能力的地方。

● 请你介绍一下gc,另外如果Java里写一个方法,这个方法里只有一条语句,即new一个对象,请问方法结束以后这个对象怎么回收的?

参考回答:
GC(garbage collection)垃圾收集,是指JVM用于释放那些不再使用的对象所占用的内存,常用的JVM都有GC,而且大多数gc都使用类似的算法管理内存和执行手机操作,GC可以通过确定对象是否被活动对象引用来确定是否收集该对象,常用的方法有引用计数和对象引用遍历
● 请你回答一下protected,public,private的区别
参考回答:
在这里插入图片描述

● 请你回答一下Java的内存结构是什么,全局变量,临时变量,静态变量分别存在哪里,堆分为哪几块,比如说新生代老生代,那么新生代又分为什么

参考回答:
代码区:是编译器生成的一个exe区段,存放函数体的二进制代码
栈区:存放函数的参数,局部变量的值等,其操作方式类似于数据结构中的栈,const局部变量也是放在栈里

堆区:就是malloc和new之类的内存所在区段,一般由程序员分配释放,分配方式类似于链表

静态数据区:是编译器生成的一个exe区段,初始和未初始化的全局变量和局部变量都放在这里,

常量区:是编译器生成的一个exe区段,const全局变量也放在常量区。

全局变量,临时变量,静态变量分别存在哪里

局部变量保存在栈中,全局变量和静态变量存储在静态数据区。

堆分为哪几块,比如说新生代老生代,那么新生代又分为什么?

java垃圾收集管理器的主要区域,因此很多时候被称为“GC堆”。

分为新生代和老年代;

新生代分为:Eden和Survivor。

● 请你回答一下c++和java的区别

参考回答:
1、C++创建对象后需要在使用结束后调用delete方法将其销毁,Java有垃圾回收机制,用来监视new出来的所有对象,辨别不会再被引用的对象,然后释放内存空间
2、当变量作为类的成员使用时,Java才确保给定默认值,以确保那些基本类型的成员变量得到初始化,但是C++没有此功能,

3、c++引入了操作符重载机制,Java不支持

4、Java中没有sizeof(),在C++中sizeof()操作符能够告诉我们为数据项分配的字节数,因为C++中不同的数据类型在不同的机器上可能有不同的大小,但是在Java中所有的数据类型在所有机器中大小都是相同的。

5、Java的运行速度比C++慢,因为Java是半解释和半编译的。

6、C++中有多继承,Java中只有单一继承,但是java可以通过接口实现多继承

7、在C++中,数组定义时,已经分配存储空间,并且可以使用,在Java中,数组定义时只定义了数组变量,数组是不可以使用的,只有数组new之后才会创建数组,并分配存储空间

8、C++有指针,Java没有。

● 请你说一说接口有什么限制
参考回答:
1、变量会被隐式地指定为public static final变量,并且只能是public static final变量,用private修饰会报编译错误
2、方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误)
3、接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法

● 请问Java中线程如何实现,如何实现多线程,线程安全在Java中是如何实现的,线程的工作区是哪里

参考回答:
Java中实现线程有三种方式:

1、1.继承Thread类

public class Thread extends Object implements Runnable

定义Thread类的子类,并重写Thread类的run()方法,创建子类对象(即线程对象),调用线程对象的start()方法来启动该线程。

2.实现Runnable接口

public interface Runnable

定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法同样是该线程的执行体。创建该Runnable实现类的实例,并将此实例作为Thread的target(即构造函数中的参数)来创建Thread对象(该Thread对象才是真正的线程对象,只是该Threa

3.使用Callable和Future

创建Callable接口的实现类,并实现call()方法,该方法有返回值;创建Callable实现类的实例,使用FutureTask来包装Callable对象,并且也封装了call()方法的返回值;使用FutureTask作为Thread类的target创建并启动线程;调用FutureTask对象的get()方法返回子线程执行结束后的返回值。

如何实现多线程:

首先是继承Thread类并重写run()方法
首先是实现Runnable接口并重写run()方法

线程安全的实现:
同步代码块、同步方法、同步锁
同步代码块:同步监视器是共享资源
同步方法:同步监视器是this
同步锁:

● 请你说一说内存溢出和内存泄漏是怎么回事
参考回答:
内存溢出out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

内存泄漏可以分为四类:

1、常发性内存泄漏,发生内存泄漏的代码会被多次执行到,每次执行都会导致内存泄漏

2、偶发性内存泄漏:发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生,

3、一次性内存泄漏,发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。

4、隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。

从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。

内存溢出常见原因:

1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3.代码中存在死循环或循环产生过多重复的对象实体;
4.使用的第三方软件中的BUG;
5.启动参数内存值设定的过小

解决方案:

1、修改JVM参数,直接增加内存

2、检查错误日志,查看内存溢出错误前是否有其他异常错误

3、对代码进行走查分析,找出可能发生内存溢出的位置

● 请你介绍一下HashMap,HashTable,ConcurrentHashMap

参考回答:
1、HashTable与HashMap
(1)HashTable和HashMap都实现了Map接口,但是HashTable的实现是基于Dictionary抽象类。

(2)在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,既可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。而在HashTable中,无论是key还是value都不能为null。

(3)HashTable是线程安全的,它的方法是同步了的,可以直接用在多线程环境中。HashMap则不是线程安全的。在多线程环境中,需要手动实现同步机制。

2、更好的选择:ConcurrentHashMap Java 5中新增了ConcurrentMap接口和它的实现类ConcurrentHashMap。 ConcurrentHashMap提供了和HashTable以及SynchronizedMap中所不同的锁机制。HashTable中采用的锁机制是一次锁住整个hash表,从而同一时刻只能有一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。ConcurrentHashMap默认将hash表分为16个桶,诸如get,put,remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。 上面说到的16个线程指的是写线程,而读操作大部分时候都不需要用到锁。只有在size等操作时才需要锁住整个hash表。 在迭代方面,ConcurrentHashMap使用了一种不同的迭代方式。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是,在改变时new新的数据从而不影响原有的数据,iterator完成后再将头指针替换为新的数据,这样iterator可以使用原来老的数据,而写线程也可以并发的完成改变。

● 请你说一下Hashset有什么特性,以及hashset判断存入的对象是否重复是如何比较的
参考回答:
HashSet是Set接口的实现类,因此,HashSet中的元素也是不能重复的。HashCode判断元素重复的标准时,首先计算新添加元素的hashCode值,当不重复是,则直接加入到该集合中,若发生重复,也称发生了碰撞,则进一步调用equals判断元素是否在逻辑上相同。

● 请你说一下Java的反射,你目前主要用他做什么,以及Java的泛型,他的主要作用是什么

参考回答:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。Java反射可以用来获取一个class对象或实例化一个class表示的类的对象,还可以获取构造方法,成员变量,成员方法。
java中泛型的引入主要是为了解决两个方面的问题:1.集合类型元素在运行期出现类型装换异常,增加编译时类型的检查,2. 解决的时重复代码的编写,能够复用算法。下面通过例子来说明编译器的类型检查。

● 请问类加载器你了解吗

参考回答:
类加载器就是把类加载阶段中的”通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到java虚拟机外部来实现的代码模块。
类加载器的分类:

启动类加载器、扩展类加载器、应用类加载器(系统类加载器)、用户自定义类加载器。
启动类加载器:这个类负责将存放在JAVA_HOME/lib目录或者被-Xbootclasspath参数所指定的路径中的并且是虚拟机内存中。
扩展类加载器:负责加载JAVA_HOME/lib/ext目录中或者被java.ext.dirs系统变量指定路径中的所有类库,开发者可以直接使用扩展类加载器。
应用程序类加载器:负责加载用户类路径上指定的类加载器,一般情况下就是程序中默认的类加载器。

● ReentranceLock 和 synchronized 有什么区别
参考回答:
1.可重入性
字面的意思就是可以再次进入的锁,synchronized其实也是可重锁,同一线程每进入一次,锁的计数器都会加一,在释放锁是计数器都会减一,只有当计数器为0 时才能释放锁

2.锁的实现

ReentrantLock是JDK实现的 Synchronized 是JVM实现
前者可以直接看到源码,后者实现难以看到

3.性能的区别

在Synchronized优化以前,synchronized的性能是比ReenTrantLock差很多的,但是自从Synchronized引入了偏向锁,轻量级锁(自旋锁)后,两者的性能就差不多了,在两种方法都可用的情况下,官方甚至建议使用synchronized,其实synchronized的优化我感觉就借鉴了ReenTrantLock中的CAS技术。都是试图在用户态就把加锁问题解决,避免进入内核态的线程阻塞。

4.功能的区别

便利性:很明显Synchronized的使用比较方便简洁,并且由编译器去保证锁的加锁和释放,而ReenTrantLock需要手工声明来加锁和释放锁,为了避免忘记手工释放锁造成死锁,所以最好在finally中声明释放锁。
锁的细粒度和灵活度:很明显ReenTrantLock优于Synchronized

当你需要时候一下三种功能是需要使用ReentrantLock

ReentranLock 可以指定公平锁还是非公平锁
(公共锁就是先等待的线程先获得锁)
实现自旋锁,通过循环调用CAS操作来实现加锁,性能比较好,避免进入内核态的线程阻塞。

提供了Condition类,可以分组唤醒需要唤醒的线程

提供能够中断等待锁的线程的机制,lock.lockInterruptibly()

具体使用场景要根据实际的业务进行分析
使用Synchronized时不需要释放锁,jvm会帮助我们做释放锁的操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值