java-JDK8基本源码源码分析

JDK源码分析

基于JDK1.8------java lang Object

Object的类中的方法(13个方法)

registerNatives()

getClass()

hashCode()

equals()

clone()

toString()

notify()

notifyAll()

wait() 有三个方法重载

finalize()

源码:

/**
 * Class {@code Object} is the root of the class hierarchy.
 * Every class has {@code Object} as a superclass. All objects,
 * including arrays, implement the methods of this class.
 *
 * @author  unascribed
 * @see     java.lang.Class
 * @since   JDK1.0
 */
public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }

   
    public final native Class<?> getClass();

    
    public native int hashCode();

    
    public boolean equals(Object obj) {
        return (this == obj);
    }

   
    protected native Object clone() throws CloneNotSupportedException;

   
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

   
    public final native void notify();

    public final native void notifyAll();

   
    public final native void wait(long timeout) throws InterruptedException;

    
    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }

   
    public final void wait() throws InterruptedException {
        wait(0);
    }

    
    protected void finalize() throws Throwable { }
}

为什么使用java lang Object包下面不需要导入包?

因为java.lang.Object是除了它自身之外的所有类的父类,所以不需要导入

导入包的方式: 1.单类型导入(提倡使用): 具体的名字直到具体到包的吓得名字 —import java.util.Iterator;

​ 2.按需求类型导包:import java.util.* 意思为下面你用到什么类型的包,系统就会给你导入你代码中需要的包(并不是将util包下面的类全部导入!)

小结:单类型导入会提高代码的运行速度,因为会针对性的去所对应的文件夹下寻找类及导入当前类中。

equals(Object obj)

public boolean equals(Object obj) {
    return (this == obj);
}

先介绍下“==”符号 每次生成对对象或者属性的同时会给改内容生成一个地址编码(经过一定算法后为hashcode)==比较的是两个对象或者属性是否有一个hashcode值,在Object源码看来 equal 与 == 是等价的 但是!每当调用equal方法的this都会重写这个equal方法,如果是自己写的类可以重写方法equal来定义自己的方法——上面叫两个对象相同如果是系统自带的类例如String对象的源码如下:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

分析:this == anObject

如果调用这个对象的他们的hashcode的值一样的话 那么确定他们是同一个字符串。

如果调用这个对象的是String的指向类型,那么就把继续判断,长度,转为字符数组后每个字符的内容是否相等,如果都相等的话返回的true。

注意点:比较时候要排除对象为空的情况 非空的x x.equal(null) 返回值为false

小结:== 比较基本数据类型为比较的值是否相同 比较引用数据类型 比较的是hashcode值。

​ equal() 比较引用数据类型 比较他们的Hashcode 基本数据类型不能使用其方法。

toSting()

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

返回值为String类型 返回的内容为 调用此访的对象所在的类的名字+一个@符号+Integer类型的的hash值加密后的数值(可以理解为内存地址)

打印某个对象时候默认的调用toString方法。

wait()

线程锁时候使用:将某个获得锁对象并且在Runnable的状态下 讲此线程转为等待池中。

notify()/notifyAll()

这个是使用锁对象线程是的时候才能使用的方法得到,先调用wait方法,在使用noti()/notifAll()使得被wait的线程可以随机分配锁对象的机会(wait等待池中转到锁等待池中再次获得锁对象)

finalize 方法

这个方法是有jvm自动调用,进行垃圾回收(简单介绍垃圾回收:该对象不再会有人指向它或者他为空的时候,jvm会自动调用此方法)

registerNatives()

private static native void registerNatives();
static {
    registerNatives();
}

此方法是native修饰的说明这个方法是c或者c++编写的;System.loadLibrary(“helloJNI”);加载动态库,参数 helloJNI 是动态库的名字

native 用来修饰方法,用 native 声明的方法表示告知 JVM 调用,该方法在外部定义,我们可以用任何语言去实现它。 简单地讲,一个native Method就是一个 Java 调用非 Java 代码的接口。

native 语法:

①、修饰方法的位置必须在返回类型之前,和其余的方法控制符前后关系不受限制。

②、不能用 abstract 修饰,也没有方法体,也没有左右大括号。

③、返回值可以是任意类型

我们在日常编程中看到native修饰的方法,只需要知道这个方法的作用是什么,至于别的就不用管了,操作系统会给我们实现。

java lang Integer

public final class Integer extends Number implements Comparable<Integer>

这个类是final修饰的 不可以被继承 继承了Number类和实现了Cmparable接口,Number 类是一个抽象类,8中基本数据类型的包装类除了Character 和 Boolean 没有继承该类外,剩下的都继承了 Number 类,该类的方法用于各种数据类型的转换。Comparable 接口就一个 compareTo 方法,用于元素之间的大小比较,下面会对这些方法详细展开介绍。

number抽象类

public abstract class Number implements java.io.Serializable {

Comparable

Comparable接口的实现方法

public interface Comparable<T> {
    public int compareTo(T o);
}

接下里就看看怎么实现Integer中的Comparable接口的

public int compareTo(Integer anotherInteger) {
    return compare(this.value, anotherInteger.value);
}
 public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

这个接口实现方法调用了自己里面的写的方法 比较两个数的大小

​ 如果 x < y 返回 -1

如果 x == y 返回 0

如果 x > y 返回 1

Integer构造器

public Integer(int value) {
    this.value = value;
}

这个在new的时候讲一个基本数据类型返回 Integer类型

   //String必须是第一位为“-或者+” 其他均为 0-9 a-z
public Integer(String s) throws NumberFormatException {
    this.value = parseInt(s, 10);
}
	public static int parseInt(String s, int radix)
                throws NumberFormatException
    {
        if (s == null) {
            throw new NumberFormatException("null");
        }
        //如果转换的radix(默认是10)<2 则抛出数字格式异常,因为进制最小是 2 进制
if (radix < Character.MIN_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                        " less than Character.MIN_RADIX");
    }
	//如果转换的radix(默认是10)>36 则抛出数字格式异常,因为0到9一共10位,a到z一共26位,所以一共36位
    //也就是最高只能有36进制数
    if (radix > Character.MAX_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                        " greater than Character.MAX_RADIX");
    }

    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    int limit = -Integer.MAX_VALUE;
    int multmin;
    int digit;

    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar < '0') { // Possible leading "+" or "-"
            if (firstChar == '-') {
                negative = true;
                limit = Integer.MIN_VALUE;
            } else if (firstChar != '+')
                throw NumberFormatException.forInputString(s);

            if (len == 1) // Cannot have lone "+" or "-"
                throw NumberFormatException.forInputString(s);
            i++;
        }
        multmin = limit / radix;
        while (i < len) {
            // Accumulating negatively avoids surprises near MAX_VALUE
            digit = Character.digit(s.charAt(i++),radix);
            if (digit < 0) {
                throw NumberFormatException.forInputString(s);
            }
            if (result < multmin) {
                throw NumberFormatException.forInputString(s);
            }
            result *= radix;
            if (result < limit + digit) {
                throw NumberFormatException.forInputString(s);
            }
            result -= digit;
        }
    } else {
        throw NumberFormatException.forInputString(s);
    }
    return negative ? result : -result;
}

toString()三个方法的重载

public static String toString(int i, int radix) {
    //第一个参数为需要转为的数据 第二个数为转为数据的进制数 最后返回一个字符串
    
    if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        radix = 10;

    /* Use the faster version */
    if (radix == 10) {
        return toString(i);
    }

    char buf[] = new char[33];
    boolean negative = (i < 0);
    int charPos = 32;

    if (!negative) {
        i = -i;
    }

    while (i <= -radix) {
        buf[charPos--] = digits[-(i % radix)];
        i = i / radix;
    }
    buf[charPos] = digits[-i];

    if (negative) {
        buf[--charPos] = '-';
    }

    return new String(buf, charPos, (33 - charPos));
}

parseInt(String s, int radix)

这个源码和Integer(String S ,int)一样

valueOf(int i)

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

调用的是构造方法里面的讲int转为Integer类型

Max()

public static int max(int a, int b) {
    return Math.max(a, b);
}
//math的max
    public static int max(int a, int b) {
        return (a >= b) ? a : b;
    }

调用的是Math的max的方法三目运算符

java lang String

类的特点

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence 

是final修饰的

接着实现了 Serializable接口,这是一个序列化标志接口,还实现了 Comparable 接口,用于比较两个字符串的大小(按顺序比较单个字符的ASCII码),后面会有具体方法实现;最后实现了 CharSequence 接口,表示是一个有序字符的集合。

String 的底层存放字符串的是private final char value[];

String(Stringbuffered buffer)

public String(StringBuffer buffer) {
    synchronized(buffer) {
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}
//arrays的copyOf方法
    public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
//system的arraycopy方法  此方法是其他语言编写的
    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

将可变的字符串转为不可变字符串-----意味着吧buffer里面的数据放到定长数组里面

toCharArray()

public char[] toCharArray() {
    // Cannot use Arrays.copyOf because of class initialization order issues
    char result[] = new char[value.length];
    System.arraycopy(value, 0, result, 0, value.length);
    return result;
}

equals(Object anObject)

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

首先比较他们的hashcode是否相等 如果相等的话那么他们就是相等的,如果他们的指向类型的是属于String的指向类型或者是String类型的话在进行一个个字符进行判断

indexof()

public int indexOf(String str) {
    return indexOf(str, 0);
}

 public int indexOf(int ch, int fromIndex) {
    final int max = value.length;//max等于字符的长度
     if (fromIndex < 0) {//指定索引的位置如果小于0,默认从 0 开始搜索
         fromIndex = 0;
    } else if (fromIndex >= max) {
         //如果指定索引值大于等于字符的长度(因为是数组,下标最多只能是max-1),直接返回-1
        return -1;
     }
 
    if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {//一个char占用两个字节,如果ch小于2的16次方(65536),绝大多数字符都在此范围内
        final char[] value = this.value;
        for (int i = fromIndex; i < max; i++) {//for循环依次判断字符串每个字符是否和指定字符相等
             if (value[i] == ch) {
                 return i;//存在相等的字符,返回第一次出现该字符的索引位置,并终止循环
            }
         }
         return -1;//不存在相等的字符,则返回 -1
     } else {//当字符大于 65536时,处理的少数情况,该方法会首先判断是否是有效字符,然后依次进行比较
         return indexOfSupplementary(ch, fromIndex);
     }
 }

intern()

public native String intern();

可以常量池里面(前提是常量里面没吃这个常量对象)

总结:String真的是不可变的嘛?不是!可以通过反射机制获取String对象,在获得定义的变量------String.class.getDeclaredField(“value”);直接获取堆里面的数组对象,对其进行修改(前提要设置setAccessible(true))因为这个是value是private修饰的

new String生成的是对象!String s=“ ”生成的常量放在常量池里面 可供下次使用,若再有相同值的String可以直接饮用之前使用过的

java util Arrays

ArrayList是Arrays 的内部类

这个方法返回的 ArrayList 不是我们常用的集合类 java.util.ArrayList。这里的 ArrayList 是 Arrays 的一个内部类 java.util.Arrays.ArrayList。只能对其进行查看修改不能对其删除和增加

private static class ArrayList<E> extends AbstractList<E>
eg:
   list list =Arrays.aslist(1,2,3,4,5);

asList()

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

aslist接受的是包装类型的数据

public  void  test(){
    int [] a=new int[]{1,23,4,6,8};
    List ints = Arrays.asList(a);
    ///ints.size()为1 只能吧整个int[] 进行泛型化
    for (int i = 0; i <ints.size() ; i++) {
        System.out.println(ints.get(i));
    }
}}
//输出结果为[I@306a30c7数组对象 
//ps:在 Arrays.asList 中,方法声明为  <T> List<T> asList(T... a)。该方法接收一个可变参数,并且这个可变参数类型是作为泛型的参数。我们知道基本数据类型是不能作为泛型的参数的,但是数组是引用类型,所以数组是可以泛型化的,于是 int[] 作为了整个参数类型,而不是 int 作为参数类型。

sort()

有十几种方法进行重载

sort(int i)

public static void sort(int[] a) {
    DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
 //在 Arrays.sort 方法内部调用 DualPivotQuicksort.sort 方法,这个方法的源码很长,分别对于数组的长度进行了各种算法的划//分,//包括快速排序,插入排序,冒泡排序都有使用。详细源码可以参考https://www.cnblogs.com/yuxiaofei93/p/5722714.html

因为具体的算法俺也不会 小辫子也只能看到这里 太长的源码看的头发也没有了!

copeOf()

public static int[] copyOf(int[] original, int newLength) {
    int[] copy = new int[newLength];
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

equal(int i)

public static boolean equals(int[] a, int[] a2) {
    if (a==a2)
        return true;
    if (a==null || a2==null)
        return false;

    int length = a.length;
    if (a2.length != length)
        return false;

    for (int i=0; i<length; i++)
        if (a[i] != a2[i])
            return false;

    return true;
}

首先判断会否是同一个对象,或者判断他们是不是都为为空,若为空则那么返回为false 再或者比较他们的长度在比较他们每个元素的内容是否相同

toString()

public static String toString(char[] a) {
    if (a == null)
        return "null";
    int iMax = a.length - 1;
    if (iMax == -1)
        return "[]";

    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; ; i++) {
        b.append(a[i]);
        if (i == iMax)
            return b.append(']').toString();
        b.append(", ");
    }
}

首先判断是否为空—空的就输出null字符 如果里面声明也没有的话返回一个[] 在否则的话进行么个数组的遍历放到一个Stringbuilder里面

分析: String [] s=null 在栈里面声明一块地址,里面没有指向的堆地址

​ String [] s={} 在栈里面有一块地址 并且指向了堆里面的内存,但是堆里面得什么都能不放

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值