Java『基础知识』

JVM

JVM是运行Java字节码的虚拟机。JVM有针对不同系统的特定实现,目的在不同的系统平台上运行相同的字节码。.java文件经过JDK的javac编译为.class文件,.class文件又被JVM编译成机器可执行的二进制机器码。

我们需要格外注意的是 .class->机器码 这一步。在这一步 jvm 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的,也就是所谓的热点代码,所以后面引进了 JIT 编译器,JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们 为什么经常会说 Java 是编译与解释共存的语言。

HotSpot采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是JIT所需要编译的部分。JVM会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。JDK 9引入了一种新的编译模式AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了JIT预热等各方面的开销。JDK支持分层编译和AOT协作使用。但是 ,AOT 编译器的编译质量是肯定比不上 JIT 编译器的。

重载与重写

重载:发生在同一类中,方法名相同,方法签名(参数类型、个数、顺序不同)可能不同;注意,返回类型和访问修饰符不算在方法签名中,不能作为重载的判断依据。

重写:发生在继承类中,方法签名需要相同,方访问权限子类中实现需要大于等于父类中实现。

构造器Constructor是否可以被override?

父类的构造方法和私有属性不能被继承,所以Constructor也不能被重写(override),但是可以被重载(overload)。

Java面向对象编程三大特性

封装、继承、多态,其中多态指定是程序的引用变量可以在运行时的向上转型动态确定。Java中可以通过继承接口实现多态。

String、StringBuilder、StringBuffer

可变性:首先String是用final修饰的保存字符的数组,因为字符串是不可变的,所以当直接定义字符串(如:"abc")时,会去常量池中寻找该变量值,存在直接返回使用,不存在再行创建;StringBuilder和StringBuffer都是继承自AbstractStringBuilder类,该类也是使用数组保存字符串,和String不同的是没有使用final修饰,所以是可变的。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
    ...
}

线程安全性:String是不可变的,所以线程安全;StringBuffer是线程安全的;StringBuilder是非线程安全的,所以性能比StringBuffer高一点。

==和equals()

默认情况下==用来比较两个对象的引用地址是否相同,或者比较两个常量(基础类型分布在常量池中)是否相等;equals用来比较对象的具体属性的值是否相等;有时我们只需要比较两个对象包含的属性值是否相等,这时可以重写equals方法来实现。

Object的hashCode()和HashMap中的hashCode()

在使用==判断两个变量是否相等,比较的是两个变量的内存地址,和Object的hashCode()并没有直接的关系;先看Object中的hashCode()

/**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * <p>
     * The general contract of {@code hashCode} is:
     * <ul>
     * <li>Whenever it is invoked on the same object more than once during
     *     an execution of a Java application, the {@code hashCode} method
     *     must consistently return the same integer, provided no information
     *     used in {@code equals} comparisons on the object is modified.
     *     This integer need not remain consistent from one execution of an
     *     application to another execution of the same application.
     * <li>If two objects are equal according to the {@code equals(Object)}
     *     method, then calling the {@code hashCode} method on each of
     *     the two objects must produce the same integer result.
     * <li>It is <em>not</em> required that if two objects are unequal
     *     according to the {@link java.lang.Object#equals(java.lang.Object)}
     *     method, then calling the {@code hashCode} method on each of the
     *     two objects must produce distinct integer results.  However, the
     *     programmer should be aware that producing distinct integer results
     *     for unequal objects may improve the performance of hash tables.
     * </ul>
     * <p>
     * As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java&trade; programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();

首先看到这是一个native方法,方法注释

  • This method is supported for the benefit of hash tables such as those provided by {@link java.util.HashMap},所以这是为什么比较两个对象是否相等(值相等使用equals,内存地址相等使用==)没有用到hashCode方法,却非要在Object类中添加对hashCode的支持的原因;
  • 在同一对象上调用多次hashCode()应该始终返回相同的int值;
  • 如果ObjA.equals(ObjB),那么ObjA的hashCode一定等于ObjB;
  • 两个对象相互equals,不代表他们的hashCode一定不相等(即所谓的哈希碰撞)。

其次HashMap只是一种数据结构,其存在的理由是为了集成类似数组的快速查找,又想避免为了存储少数大范围值的数据而创建一个大数组的问题。通过hash函数可以把这些大范围值的数据映射到HashMap的数组中去,如果发生哈希碰撞,则会是使用链表,而在Java 8.0以后,使用红黑树替代了链表;

具体HashMap可参考:HashMap实现原理及源码分析

equals()和hashCode()

​ 以HashSet为例,当需要插入、查询一个对象时,先计算该对象的hashCode,看是否存在相同的hashCode,如果存在,再对比他们的equals方法是否相等,如果equals方法也相等,则表明是同一个对象,拒绝插入;如果equals方法不相等,则对对象的重新进行hash,插入到其他位置。

Java中的序列化和反序列化(Serializable)

Java序列化就是将一个对象转化为一个****二进制表示的字节数组,如果不想对某些字段进行序列化,可以使用transient关键字修饰;在反序列化时如果serialVersionUID被修改的话,反序列化会失败;当父类实现了Serializable接口的时候,所有的子类都能被序列化,当子类实现Serializable接口时,父类没有,则父类中的属性不能被序列化。

Collections类和Arrays工具类的常用方法

Collections类
  • 排序:sort(List)、sort(List, Comparator)、swap(list, i , j)
  • 查找:binarySearch(list , key)、max(Collection)、indexOfSubList(List list, List target)
  • 替换:replaceAll(List list, Object oldVal, Object newVal)
Arrays类
  • 排序:sort(List)
    val iArray = intArrayOf(1, 3, 4, 5, 6, 7, 8, 8, 6, 5, 4)
        Arrays.sort(iArray)
        for (v in iArray) {
            print("$v ")
        }
    >>>输出:1 3 4 4 5 5 6 6 7 8 8
  • 比较:equals()
    val arrayA = intArrayOf(1,3,5)
    val arrayB = intArrayOf(1,3,5)
    println(Arrays.equals(arrayA,arrayB))
    >>>输出:true
  • 转列表:asList()
    val names = Arrays.asList("Larry", "Moe", "Curly")
    println(names)
    >>>输出:[Larry, Moe, Curly]

Java基础关键字

final
  • 当final用来修饰变量时,如果变量是基本数据类型,则其数值不能改变;如果变量时引用类型,则改变量不能在再指向另一个对象。
  • 当一个方法被final修饰时,表示该方法不能被继承类重写。
  • 当一个类使用final修饰时,该类不能被继承,该类中所有方法都会隐式的被定义为final方法
static
  • 被static修饰的成员属于类,被类中所有对象共享,静态变量被分配在方法区,被所有线程共享。
  • 静态代码块,静态代码在非静态代码执行之前执行,且不管改类创建多少对象,静态代码只执行一次
  • 静态内部类,和非静态内部类最大的区别在于,非静态内部类在编译后会隐含地保存着一个指向创建他的外部类的引用,而静态内部类没有这个引用。经常这里会问到内存泄露的问题。
为什么static方法中不能使用this和super?

static修饰静态方法是属于类的;而this指向当前对象,super代表父类对象引用;静态方法属于类,而this、super针对对象。同样的问题还有:为什么不能在静态方法内调用外部类的非静态成员?一样的答案。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,882评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,208评论 3 414
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,746评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,666评论 1 309
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,477评论 6 407
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,960评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,047评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,200评论 0 288
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,726评论 1 333
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,617评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,807评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,327评论 5 358
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,049评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,425评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,674评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,432评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,769评论 2 372

推荐阅读更多精彩内容

  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,674评论 0 11
  • 九种基本数据类型的大小,以及他们的封装类。(1)九种基本数据类型和封装类 (2)自动装箱和自动拆箱 什么是自动装箱...
    关玮琳linSir阅读 1,896评论 0 47
  • 1.java中==和equals和hashCode的区别 1)==若是基本数据类型比较,是比较值,若是引用类型,则...
    Fitz_e74a阅读 4,477评论 1 1
  • 1. 面向对象和面向过程的区别 面向过程 优点:性能比面向对象高缺点:消耗资源比面向过程多,且不易维护、复用、扩展...
    驍君阅读 331评论 0 0
  • 1. 面向对象与面向过程的区别 面向过程: 面向过程性能比面向对象高,因为类对象调用需要实例化,开销比较大,比较消...
    烦人的胆小鬼阅读 197评论 0 1