float a = 1f;
float b = 0.9f;
float f = a-b;
// 输出
// 0.100000024
lsof -n | awk '{print $2} '| sort |uniq -c |sort -nr|more
ps -ax | grep 32764
net.ipv4.tcp_fin_timeout=30(建议小于30秒为宜)
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a,S[a]}'
netstat -ant |grep -i "443" |grep CLOSE_WAIT|wc -l
类的定义
接口与抽象类
内部类
public class OuterClass{
// 成员内部类
private class InstanceInnerClass{}
// 静态内部类
static class StaticInnerClass{}
public static void main(String[] args){
// 两个匿名内部类 分别对应 OuterClass$1 和 OuterClass$2
(new Thread() {}).start();
(new Thread() {}).start();
// 两个方法内部类 分别对应 OuterClass$1MethodClass1 和 OuterClass$1MethodClass2
class MethodClass1{}
class MethodClass2{}
}
}
```
* 无论时什么类型的内部类,都会编译成一个独立的 .class 文件。外部类与内部类之间使用 $ 符号分隔,匿名内部类使用数字进行编号,而方法内部类,在类名前还有一个编号来识别时哪个方法。静态内部类时最常用的内部表现形式,外部可以使用 OuterClass.StaticInnerClass 直接访问,类加载与外部类在同一个阶段进行,在 JDK 源码中,定义包内可见静态内部类的方式很常见,这样的好处是:
* 作用域不会扩散到包外
* 可以通过“外部类.内部类”的方式直接访问
* 内部类可以访问外部类中所有静态属性和方法
访问权限控制
this和super
类关系
序列化
方法
long f(){
return 1L;
}
double f(){
return 1.0d;
}
var a = f();
public class ParamPassing{
private static int intStatic = 222;
private static String stringStatic = "old stirng";
private static StringBuilder stringBuilderStatic = new StringBuilder("old stringBuilder");
public static void main(String[] args){
// 实参调用
method(intStatic);
method(stringStatic);
method(stringBuilderStatic, stringBuilderStatic);
// 输出依然是222(第一处)
System.out.println(intStatic);
method();
// 无参方法调用之后,反而修改为888(第二处)
System.out.println(intStatic);
// 输出依然是:old string
System.out.println(stringStatic);
// 输出结果参考下方分析
System.out.println(stringBuilderStatic);
}
// A方法
public static void method(int intStatic){
intStatic = 777;
}
// B 方法
public static void method(){
intStatic = 888;
}
// C 方法
public static void method(String stringStatic){
// String 是immutable 对象,String没有提供任何方法用于修改对象
stringStatic = "new string";
}
// D 方法
public static void method(StringBuilder stringBuilderStatic1, StringBuiler stringBuilderStatic2){
// 直接使用参数引用修改对象(第三处)
stringBuilderStatic1.append(".method.First-");
stringBuilderStatic2.append("method.second-");
// 引用重新赋值
stringBuilderStatic1 = new StringBuilder("new stringBuilder");
stringBuilderStatic1.append("new methods`s append");
}
}
// 第一处
1. SIPUSH 777
2. ISTORE 0
3. RETURN
// 第二处
1. SIPUSH 888
2. PUTSTATIC ParamPassing.intStatic:
3. RETURN
public static method(Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;)v
L0
ALOAD 0
LDC ".method.first"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;) Ljava/lang/StringBuilder;
POP
L1
ALOAD 1
LDC "method.second"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;) Ljava/lang/StringBuilder;
POP
L2
NEW java/lang/StringBUilder
DUP
LDC "new stringBuilder"
INVOKESPECIAL java/lang/StringBuilder.<init> (Ljava/lang/String;) V
ASTORE 0
L3
ALOAD 0
LDC "new method's append"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;) Ljava/lang/StringBUilder;
POP
RETURN
class Son extends Parent {
static { System.out.println("Son 静态代码块"); }
Son() { System.out.println("Son 构造方法"); }
public static void main(String[] args) {
new Son();
new Son();
}
}
class Parent {
static { System.out.println("Parent 静态代码"); }
public Parent() { System.out.println("Parent 构造方法");}
}
// 输出
// Parent 静态代码块
// Son 静态代码块
// Parent 构造方法
// Son 构造方法
// Parent 构造方法
// Son 构造方法
public class StaticCode {
// prior 必须定义在last 前边,否则编译出错:illegal forword reference
static String prior = "done";
// 以此调用 f() 的结果,三目运算符为 true,执行 g(),最后赋值成功
static String last = f() ? g():prior;
public static boolean f(){
return true;
}
public static String g(){
return "hello world";
}
static {
// 静态代码块可以访问静态变量和静态方法
System.out.println(last);
g();
}
}
重载
public class SameMethodSignature {
public void methodForOverload () {}
// 编译出错,返回值并不是方法签名的一部分
public final int methodForOverload () { return 7; }
// 编译出错,访问控制符也不是方法签名的一部分
private void methodForOverload () {}
// 编译出错,静态标识符也不是方法签名的一部分
public static void methodForOverload () {}
// 编译出错,final标识符也不是方法签名的一部分
private final void methodForOverload () {}
}
public void methodForOverload(int paraml, Integer param2) {}
public void methodForOverload(Integer param3, int param4) {}
// 若调用 methodForOverload(13, 14) 会抛异常
泛型
public class GenericDefinitionDemo<T> {
static <String, T, Alibaba> String get(String string, Alibaba alibaba){
return string;
}
public static void main(String[] args){
Integer first = 222;
Long second = 333L;
Integer result = get(first,second);
}
}
INVOKESTATIC com/alibaba/easy/coding/generic/GenericDefinitionDemo.get (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
CHECKCAST java/lang/Integer
数据类型
在冯·诺伊曼定义的计算机模型中,任何程序都需要加载到内存才能与 CPU 进行交流,字节码.class 文件需要加载到内存中在可以实例化类。而 ClassLoader 就是提前加载 .class 类文件到内存中,在加载类时,使用的是 Parents Delegation Model,译为双亲委派模式,意译的话叫做"溯源委派加载模型"更为贴切
Java 的类加载器是一个运行时核心基础模块,主要在启动之初进行类的 Load、Link 和 Init,即加载、链接、初始化
类加载是一个将 .class 字节码文件实例化成 Class 对象并进行相关初始化的过程。在这个过程中,JVM 会初始化继承树上还没被初始化过的所有父类,并且会执行这个链路上所有未执行过的静态代码块、静态变量赋值语句等。某些类在使用时,也可以按需由类加载器进行加载
全小写的 class 是关键字,用来定义类,而首字母大写的 Class,它是所有 class 的类
public class ClassTest {
// 数组类型有一个魔法属性:length来获取数组长度
private static int[] array = new int[3];
private static int length = array.length;
// 任何小写class定义的类,也有一个魔法属性:class,来获取此类的大写 Class 类对象
private static Class<One> one = One.class;
private static Class<Another> another = Another.class;
public static void main(String[] args) throws Exception{
// 通过newInstance方法创建One 和Another的类对象(第一处)
One oneObject = one.newInstance();
oneObject.call();
Another anotherObject = another.newInstance();
anotherObject.speak();
// 通过one这个大写的Class对象,获取私有成员属性对象Field(第二处)
Field privateFieldInOne = one.getDeclaredField("inner");
// 设置私有对象可以访问和修改(第三处)
privateFiledInOne.setAccessible(true);
privateFiledInOne.set(oneObject, "world changed.");
// 成功修改类的私有属性inner变量值未word changed。
System.out.println(oneObject.getInner());
}
}
class one{
private String inner = "time flier.";
public void call(){
System.out.println("hello world.");
}
public String getInner(){
return inner;
}
}
class Annother{
public void speak(){
System.out.println("easy coding.");
}
}
// 输出
// hello world.
// easy coding.
// world changed.
ClassLoader c = TestWhoLoad.class.getClassLoader();
ClassLoader c1 = c.getParent();
// 由于bootstrap 是通过 C/C++ 实现的,并不存在于 JVM 体系内,所以输出为 null
ClassLoader c2 = c1.getParent();
// 输出 jdk8
// sun.misc.Launcher\$AppClassLoader@14dad5dc
// sun.misc.launcher\$ExtClassLoader@6e0be858
// null
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for(java.net.URL url : urls){
System.out.println(url.toExternalForm());
}
-Xbootclasspath/a:/Users/yangguangbao/book/easyCoding/byJdk11/src
public class CustomerClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException{
try{
byte[] result = getClassFormCustomerPath(name);
if (result == null ) {
throw new FileNotFoundException();
} else {
return defineClass(name, result, 0, result.length);
}
} catch (Exception e){
e.printStackTrace();
}
throws new ClassNotFoundException(name);
}
private byte[] getClassFromCustomerPath(String name){
// 从自定义路径中加载指定类
}
}
public static void main(String[] args){
CustomerClassLoader customerClassLoader = new CustomerClassLoader();
try{
Class<?> clazz = Class.forName("one", true, customerClassLoader);
Object obj = clazz.newInstance();
System.out.println(obj.getClass().getClassLoader());
} catch(Exception e){
e.printStackTrace();
}
}
// 输出
// classloader.CustomerClassLoader@5e481248
public int simpleMethod(){
int x = 13;
int y = 14;
int z = x + y;
return z;
}
public simpleMethod();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=2, loacls=4, args_Size=1 // 最大栈深度为2,局部变量个数为4
BIPUSH 13 // 常量13压入操作栈
ISTORE_1 // 并保存到局部变量表的slot_1中(第一处)
BIPUSH 14 // 常量14压入操作栈,注意是BIPUSH
ISTORE_2 // 并保存到局部变量表的slot_2中
ILOAD_1 // 把局部变量表的slot_1元素(int x)压入操作栈
ILOAD_2 // 把局部变量表的slot_2元素(int y)压入操作栈
IADD // 把上方的两个数都取出来,在CPU里加一下,并压回操作栈的栈顶
ISTORE_3 // 把栈顶的结果存储到变量表的slot_3中
ILOAD_3
IRETURN // 返回栈顶元素
stack=2,locals=1,args_size=0
NEW java/lang/Object
BUP
INVOKESPECIAL java/lang/Object.<init> ()V
ASTORE_1
LocalVariableTable:
Start Length Slot Name Signature
8 1 0 ref Ljava/lang/Object;
public static int finallyNotWork() {
int temp = 10000;
try {
throw new Exception();
} catch (Exception e) {
return ++temp ;
}finally {
temp = 99999;
}
}
// 输出
// 10001
public class TryCatchFinally{
static int x = 1;
static int y = 10;
static int z = 100;
public static void main(String[] args){
int value = finallyReturn();
System.out.println("Value=" + value);
Systme.out.println("x=" + x);
Systme.out.println("y=" + y);
Systme.out.println("z=" + z);
}
public static int finallyReturn(){
try{
// ...
return ++x;
}catch(Excepton e){
return ++y;
}finally{
return ++z;
}
}
}
// 输出
// value=101
// x=2
// y=10
// z=101
Lock lock = new XxxLock();
preDo();
try{
// 无论加锁是否成功,unlock 都会执行
lock.lock();
doSomething();
}finally{
lock.unlock();
}
<dependency>
<groupid>org.slf4]groupid>
<artifactid>slf4j-apiartifactid>
<version>${slf4j-api.version}version>
dependency>
<dependency>
<groupid>ch.qos.logbackgroupid>
<artifactid>logback-classicartifactid>
<version>${logback-classic.version}version>
dependency>
<dependency>
<groupid>ch.qos.logbackgroupid>
<artifactid>logback-coreartifactid>
<version>${logback-core.version}version>
dependency>
<dependency>
<groupid>org.slf4jgroupid>
<artifactid>slf4j-apiartifactid>
<version>${slf4j-api.version}version>
dependency>
<dependency>
<groupid>org.slf4jgroupid>
<artifactid>slf4j-log4j12artfactid>
<version>${slf4j-log4j12.version}version>
dependency>
<dependency>
<groupid>log4jgroupid>
<artifactid>log4jartifactid>
<version>${log4j.version}version>
dependency>
<dependency>
<groupid>org.slf4jgroupid>
<artifactid>log4j-over-slf4jartifactid>
<version>${log4j-over-slf4j.version}version>
dependency>
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final int DEFAULT_CAPACITY = 10;
// 空表的表示方法
private static final Object[] EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
// 值大于0时,根据构造方法的参数值,忠实地创建一个多大的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
}
}
// 公开的 add 方法调用此内部私有方法
private void add(E e, Object[] elementData, int s) {
// 当前数组能否容纳size+1的数组,如果不够则调用grow来扩展
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
private Object[] grow() {
return grow(size + 1);
}
// 扩容的最小要求,必须满足容纳刚才的元素个数+1,注意,newCapacity()
// 方法才是扩容的重点
private Object[] grow(int minCapacity) {
return elementData = Arrays.copyof(elementData, newCapacity(minCapacity));
}
private int newCapacity(int minCapacity) {
// 防止扩容1.5倍后超过int的表示范围(第一处)
int oldCapacity = elementData.length;
// JDK6之前扩容50%或50%-1,但是取ceil,而之后的版本取floor(第二处)
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity- minCapacity <=0) {
if (elementData == DEFAULTCAPACITY_EMPTY_ ELEMENTDATA)
// 无参数构造方法,会在此时分配默认10的容量
return Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity < 0 )
throw new OutOfMemoryError();
return minCapacity;
}
return (newCapacity - MAX_ARRAY_SIZE <= 0)? newCapacity:hugeCapacity(minCapacity);
}
}
public v put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
// ...省略代码
}
// 第一次put时,调用如下方法,初始化table
private void inflateTable(int toSize) {
// 找到大于参数值且最接近2的幂值,假如输入参数是27则返回32
int capacity = roundUpToPowerOf2{toSize};
// threshold 在不超过限制最大值的前提下等于 capacity * loadFactor
threshold = (int)Math.min(capacity * loadFactory, MAXIMUM_CAPACITY + 1);
table = new Entry[capacity];
initHashSeedAsNeeded(capacity);
}
public class ListNoGeneric {
public static void main(String[] args){
// 第一段:泛型出现之前的集合定义方式
List a1 = new ArrayList();
a1.add(new Object());
a1.add(new Integer(111));
a1.add(new String("hello a1a1"));
// 第二段:把a1引用赋值给a2,注意a2与a1的区别是增加了泛型限制