avatar

正进一步

只有喜欢,才会全情投入,才会成功!!!

不关注架构设计细节的程序员不是一个好架构师

  • Home
  • Tags
  • Categories
  • Archives
  • 2018寄语
effective_52通过接口引用对象

尽量使用接口引用对象

不用接口引用的情况:

没有合适的接口的情况。例如: 值类型,String和StringBuilder,Random。通常是final类型.
如果程序依赖于实现了某个接口的类的额外方法,例如LinkedHashMap

effective_51_当心字符串连接的性能

不要使用字符串连接操作符来合并多个字符串,除非性能无关紧要。相反,应该使用StringBuilder的append方法。另一种方法是,使用字符数组,或者每次只处理一个字符串,而不是将它们组合起来。
以为字符串的不可变,当两个字符串连接在一起时,他们的内容就会被拷贝

1
2
3
4
5
StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH);
for(int i = 0; i < numItem(); i++){
b.append(lineForItem(i));
}
return b.toString();
effective_49基本类型优先于装箱基本类型

知识:

当程序进行涉及到装箱和拆箱基本类型和混合类型计算时,会进行拆箱

基本类型和装箱基本类型之间的三个主要区别:

1.基本类型只有值,而装箱基本类型具有与它们的值不同的同一性(两个装箱基本类型可以具有相同的值和不同的同一性)

2.基本类型只有功能完备的值,而每个装箱基本类型除了它对应的基本类型的所有功能值之外,还有个非功能值:null

3.基本类型通常比装箱基本类型更节省空间和时间。

适合使用装箱基本类型的地方:

1.作为集合中的元素,键和值。

2.在参数化类型中,必须使用装箱基本类型作为类型参数。

3.在进行反射方法调用时,必须使用装箱基本类型。

effective_46_foreach循环优先于传统的for循环

foreach可以遍历iterable接口
foreach循环在简洁性与预防bug方面有着传统的for循环无法比拟的优势.

除了一下情况:

过滤- 将删除特定元素remove方法
转换- 使用列表迭代器或者数组索引,以便设定元素的值
平行迭代- 如果并行遍历多个集合,就需要显示的控制迭代器和索引变量

effective_45_将局部变量的作用域最小化

http://blog.csdn.net/zhtzyh2012/article/details/46675065

循环提供特殊机会将变量作用域最小化.(无论传统for,还foreach).for循环,都允许声明循环变量,它们的作用域被限定在正好的作用范围之内.(范围包括循环体,以及循环体之前的初始化,测试,更新).如果循环终止之后不再需要循环变量内容,for循环优于while循环.
几乎每个局部变量的声明都应该包含一个初始化表达式.如果没有足够信息来对一个变量进行有意义的初始化,就应该推迟这个声明,直到可以初始化为止.例外情况是与try..catch有关.
for循环比while循环另外优势:更简短,增加可读性.

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
Class<?>cl = null;
try{
cl= Class.forName(args[0]);
}catch (ClassNotFoundException e){
System.err.println("Classnot find");
System.exit(1);
}

}
Jdk_Proxy代理生成过过程源码分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";

// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();

@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}

String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}

if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}

/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;

/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
Jdk_Proxy生成的代理源代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.sun.proxy;

import book.base.DynamicProxyServiceTest.DynamicService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements DynamicService {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;

public $Proxy0(InvocationHandler var1) throws {
super(var1);
}

public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}

public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

public final void say() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("book.base.DynamicProxyServiceTest$DynamicService").getMethod("say");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
1
2
3
public Object getProxy(){
return Proxy.newProxyInstance(MyInvocationHandler.class.getClassLoader(),target.getClass().getInterfaces(),this);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);

final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}

/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);

/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}

final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
1
2
3
4
5
6
7
8
9
10
11
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}

// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);

expungeStaleEntries();

Object cacheKey = CacheKey.valueOf(key, refQueue);

// lazily install the 2nd level valuesMap for the particular cacheKey
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}

// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;

while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)

// lazily construct a Factory
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}

if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
43返回零长度的数组或集合,而不是null

Collections.emptyList().toArray(new Person[0]);

此处可以参考阿里Java编程规范手册

使用toArray带参方法,入参分配的数组空间不够大时,toArray方法内部将重新分配内存空间,并返回新数组地址;如果数组元素大于实际所需,下标为[ list.size() ]的数组元素将被置为null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致。

Collections.emptyList()

33用EnumMap代替序数索引

最好不要用序数来索引数组,而要使用EnumMap

EnumMap源代码学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 public V put(K key, V value) {
typeCheck(key);

int index = key.ordinal();
Object oldValue = vals[index];
vals[index] = maskNull(value);
if (oldValue == null)
size++;
return unmaskNull(oldValue);
}

public V remove(Object key) {
if (!isValidKey(key))
return null;
int index = ((Enum<?>)key).ordinal();
Object oldValue = vals[index];
vals[index] = null;
if (oldValue != null)
size--;
return unmaskNull(oldValue);
}

public V get(Object key) {
return (isValidKey(key) ?
unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
}

public boolean containsKey(Object key) {
return isValidKey(key) && vals[((Enum<?>)key).ordinal()] != null;
}

Java等号右边计算过程_i++例子

查缺补漏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public static void main(String[] args) {
int i = 0;
int m = 0;
for (int j = 0; j < 10; j++) {
{
i=i++;
}
{ //相当于下面的代码
int temp= m;
m++;
m= temp;
}
}
System.out.println("i的最后结果"+i);
System.out.println("m的最后结果"+m);
}

结果:

1
2
i的最后结果0
m的最后结果0

Volatile作用及面试内容

引用自: https://mp.weixin.qq.com/s/bvqVBnYPdFvpQqdB_4kdUQ

volatile 能使得一个非原子操作变成原子操作吗?

一个典型的例子是在类中有一个long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为 Java 中读取long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或double 变量的读写是原子。

volatile 类型变量提供什么保证?

volatile 变量提供顺序和可见性保证,例如,JVM或者 JIT为了获得更好的性能会对语句重排序,但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。 volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。某些情况下,volatile 还能提供原子性,如读 64 位数据类型,像 long 和 double 都不是原子的,但 volatile 类型的 double 和 long 就是原子的。

volatile 修饰符的有过什么实践?

一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是64位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但Java 中 volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(writebarrier),读一个volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。

21用函数对象表示策略

实现函数对象的几种方式:

  • C语言的函数指针
  • lambda表达式
  • 函数式接口

函数对象主要用于策略模式.只用一次的话,使用匿名内部类;多次使用的话,可以导出成一个成员域(static final修饰)

实例:
java.util.Comparator