1.除了new以外,还有哪些创建对象的方式呢?
答:在java中,可以通过以下几种方式创建一个对象。
(1)new 构造方法() ;
(2)使用newInstance()方法,此方法的返回值就是一个对象。不过,需要注意的是,在JDK的java.lang.reflect.Constructor和java.lang.Class两个类中,都存在着newInstance()方法,这两个newInstance()方法都可以用于创建对象,其源码如下所示。
①Class类中的newInstance()
public final class Class implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement {
...
@CallerSensitive
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
}
// NOTE: the following code may not be strictly correct under
// the current Java memory model.
// Constructor lookup
if (cachedConstructor == null) {
if (this == Class.class) {
throw new IllegalAccessException(
"Can not call newInstance() on the Class for java.lang.Class"
);
}
try {
Class>[] empty = {};
final Constructor c = getConstructor0(empty, Member.DECLARED);
// Disable accessibility checks on the constructor
// since we have to do the security check here anyway
// (the stack depth is wrong for the Constructor's
// security check to work)
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Void run() {
c.setAccessible(true);
return null;
}
});
cachedConstructor = c;
} catch (NoSuchMethodException e) {
throw (InstantiationException)
new InstantiationException(getName()).initCause(e);
}
}
Constructor tmpConstructor = cachedConstructor;
// Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers();
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
Class> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller;
}
}
// Run constructor
try {
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
}
}
②Constructor类中的newInstance()
public final class Constructor extends Executable {
...
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}
}
(3)使用Object提供的clone()方法 【clone()会在jvm中创建一个新的对象】。其源码如下所示。
public class Object {
...
protected native Object clone() throws CloneNotSupportedException;
}
(4)使用对象流(ObjectInputStream)的readObject()方法,实际就是一个反序列化操作,其源码如下所示。
public class ObjectInputStream
extends InputStream implements ObjectInput, ObjectStreamConstants
{
...
public final Object readObject()
throws IOException, ClassNotFoundException
{
if (enableOverride) {
return readObjectOverride();
}
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
try {
Object obj = readObject0(false);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
throw ex;
}
if (depth == 0) {
vlist.doCallbacks();
}
return obj;
} finally {
passHandle = outerHandle;
if (closed && depth == 0) {
clear();
}
}
}
}
(5)JVM隐式操作
JVM底层也会帮我们隐式的创建一些对象,最常见的就是JVM方法区中常量池里的对象了。例如,当我们编写 String str = "abc"时,在String常量池中就会创建一个"abc"对象。
好,最后总结一下在Java中创建对象的方式:
(1)new;
(2)- (3)使用java.lang.reflect.Constructor或java.lang.Class类中的newInstance()方法;
(4)使用对象流(ObjectInputStream)的readObject()方法;
(5)JVM隐式操作;
2.老师,每次一说到缓存中间件,就会提到Redis。那么,还有其他常用的缓存中间件吗?
答:除了Redis以外,目前SSDB也是一款流行的缓存中间件。SSDB是基于google levelDB 存储引擎,它的最大的特点是将数据直接缓存到硬盘上(Redis是缓存在内存中),因此使用SSDB不用考虑内存容量问题。非常值得注意的是:虽然 SSDB 是将数据缓存在硬盘,但却与Redis的读写性能却相差不远(一般而言,读性能,SSDB > Redis ;写性能,Redis > SSDB )。
SSDB 还支持主从同步、负载均衡和持久化队列等特性,并且 SSDB 在设计时就考虑到了与 Redis 的兼容问题,兼容 Redis API,甚至支持使用Redis客户端访问 SSDB 。
- 完 -
推荐阅读
Java小白到大神的心路历程(Java SE)
答疑 | 面试全对,却没offer?
答疑 | 背下这300字,面试就能加薪!