第二部门:实战练习

  昨天由于时间原因,这个部分应该在同一个文章中的,无奈只能今天再开一个了,今天主要是讲一些面试题

一:equals和==的区别

  最简单的面试题,也是最基础的,我估计每个学习java的人都在网上看到过该问题,答案一额很简单:equals是方法,当然只能对象来调用,所以equals只能用来比较引用类型,若该类型重写了equals方法,那比较的就是内容,比如说String类就是比较的每一对对应的字符,==既能比较基本类型,也能比较引用类型,基本类型比较的是值,引用类型比较的是地址值,总之==比较的是栈内存空间中存放的数值。

二:hashCode方法返回的是什么,有什么用

  首先看几行代码,对于没重写hashCode方法的类的对象,返回的是该对象在堆内存空间的内存地址。也就是和System.identityHashCode方法返回的一样,System.indetityHashCode返回的就是地址值。

        Student stu = new Student();
System.out.println(stu.hashCode());//
System.out.println(System.identityHashCode(stu));//

对于重写hashCode方法的类,我们拿String来举例,每个自字符串的哈希码其实是通过一个表达式来计算的s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],s[0]是指下标为0的字符的二进制数的十进制表示,对于a来说就是97(ASCII码表可查)

        System.out.println("a".hashCode());//97            97=97*31^0
System.out.println("aa".hashCode());//3104      3104=97+97*31^1
System.out.println("aaa".hashCode());//96321     96321=3104+97*31^2
System.out.println("aaaa".hashCode());//2986048    。。。
System.out.println("aaaaa".hashCode());//92567585    。。。
System.out.println("aaaaaa".hashCode());//-1425372064    因为返回的是int类型,这里越界了,所有事负数
System.out.println("aaaaaaa".hashCode());//-1236860927
System.out.println("aaaaaaaa".hashCode());//
System.out.println("aaaaaaaaa".hashCode());//

所有,我们现在明白了重写hashCode是通过某个表达式,来规定一个哈希码,这个值在很大程度上保证了唯一性,但是因为越界有可能存在俩个不同的字符串但却有相同的哈希码,所以hashCode的作用是在哈希表数据结构中(比如hashTable,hashMap)来判断俩个元素是否相等的第一个条件,若不相等,那么这两个元素的内容肯定不相等(因为他们都是通过某个同样的表达式对属性进行操作得到的),若相等,则再进行equals的比较。

特此声明:对于将要往哈希表数据结构中存放的类型必须重写hashCode方法,因为如果不重写,hashCode返回的就是地址值,那每两个new出来的对象的地址值一定不相等,但是他们的内容却一样,这不乱套了么

        String s1 = "gollong";
String s2 = new String(s1);
System.out.println(s1.hashCode());//
System.out.println(s2.hashCode());//
System.out.println(s1==s2);//false
System.out.println(System.identityHashCode(s1));//
System.out.println(System.identityHashCode(s2));//1846274136

例如:由于不重写hashCode,set集合当中存入了两个一样的对象

        HashSet<Student> set = new HashSet<Student>();
Student s1 = new Student("gol", 1.0, 1);
Student s2 = new Student("gol", 1.0, 1);
System.out.println(s1.hashCode());//
System.out.println(s2.hashCode());//
set.add(s1);
set.add(s2);
System.out.println(set);
//[Student [name=gol, scaly=1.0, age=1], Student [name=gol, scaly=1.0, age=1]]

三:intern方法的作用

  我相信知道这个方法的人很少,明白它是做什么的更少,这就涉及到昨天的那个String s = new String("gollong")创建了几个对象,答案在下图中

现在存在两个对象,一个在堆中,一个在常量池中,我们知道现在的这个s引用指向的是堆内存中的这个"gollong",而intern方法的作用就是将这个引用的指向直接改到常量池中的"gollong"上,也就是变成这样:

所以在下面的代码中,s1和s2.intern的地址值是一样的,本来s2是指向堆内存中的。现在指向了常量池中。

        String s1 = "gollong";
String s2 = new String(s1);
System.out.println(s1.hashCode());//
System.out.println(s2.hashCode());//
System.out.println(s1==s2);//false
System.out.println(System.identityHashCode(s1));//
System.out.println(System.identityHashCode(s2));// System.out.println(s1==s2.intern());//true
System.out.println(System.identityHashCode(s1));//
System.out.println(System.identityHashCode(s2.intern()));//

四:s = "" 和 s = new String("")有什么区别

  这个问题,咋一看你觉得自己不知道,其实他俩和s = "gollong" ,s = new String(""gollong)没有任何区别,都有对象的引用,字符串(虽然书空的)也分别存放在堆中和常量池中,详情见下面代码中的地址值。空字符串的哈下面默认为0.

        String s3 = "";
String s4 = new String();
System.out.println(s3==s4);//false
System.out.println(s3.hashCode());//
System.out.println(s4.hashCode());//
System.out.println(System.identityHashCode(s3));//
System.out.println(System.identityHashCode(s4));//

五:String对象的初始化时机:

  我们都知道java程序是需要通过先编译生成class文件再执行的,那么在编译的时候其实是对一些代码进行转换到,比如说下面的代码同样是+号链接俩个字符串对象,为什么s3==s4是true

        String s1 = "gol";
String s2 = "long";
String s3 = "gollong";
String s4 = "gol"+"long";
String s5 = s1+s2;
String s6 = s1+"long";
String s7 = "gol"+s2;
System.out.println(s3==s4);//true
System.out.println(s3==s5);//false
System.out.println(s3==s6);//false
System.out.println(s3==s7);//false

下面是通过反编译器的到的class文件代码

        String s1 = "gol";
String s2 = "long";
String s3 = "gollong";
String s4 = "gollong";
String s5 = (new StringBuilder(String.valueOf(s1))).append(s2).toString();
String s6 = (new StringBuilder(String.valueOf(s1))).append("long").toString();
String s7 = (new StringBuilder("gol")).append(s2).toString();
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s3 == s6);
System.out.println(s3 == s7);

我们很清楚的看到了虽然都是+号,但是是有区别的,当编译器识别到左右两端都是常量时,将直接在常量池中创建该对象,然后直接赋值,而对于变量名s1或s2由于编译器并不不知道他们的值是多少,其实得到的是一个在堆中的String对象,其地址值当然和常量池中的不一样了!

string类总结第二部分实战练习的更多相关文章

  1. Java中String类两种实例化的区别(转)

    原文:http://blog.csdn.net/wangdajiao/article/details/52087302 一.String类的第一种方式 1.直接赋值 例:String str = &q ...

  2. <CPP学习 第二天> 字符串的输入 及 String类

    今天简单的学习了字符串的输入以及C++的String类. 1.面向行的输入: getline(); getline()函数读取整行,通过回车键输入的换行符来确定输入结尾.要调用这种方法,可以使用cin ...

  3. Java第二次作业——数组和String类

    Java第二次作业--数组和String类 学习总结 1.学习使用Eclipse关联jdk源代码,查看String类的equals()方法,截图,并学习其实现方法.举例说明equals方法和==的区别 ...

  4. JAVA学习第二十九课(经常使用对象API)- String类

    多线程告一段落,開始经常使用对象API的涉及,背也要背下来!.! 日后开发,遇见最多的对象是文字,也就是字符串 String类 字符串是一个特殊对象 字符串一旦初始化就不能够被改变 一.特点 publ ...

  5. Java第二次作业--数组和String类

    Deadline: 2017-3-28 23:00 一.学习要点 认真看书并查阅相关资料,掌握以下内容: 掌握基本数据类型和引用数据类型的区别 理解对象的生成与引用的关系 掌握构造方法的重载 掌握St ...

  6. string类总结第一部分函数介绍

    在前面几章,看了整个String类的源码,给每个方法都行写了注释,但是太过凌乱,今天我就把String类的方法整理归纳,然后再讲一下String类比较难以理解的部分 特此声明:本文篇幅较大,涵盖知识点 ...

  7. 05_整理String类的Length()、charAt()、 getChars()、replace()、 toUpperCase()、 toLowerCase()、trim()、toCharArray()使用说明

    Question: 整理String类的Length().charAt(). getChars().replace(). toUpperCase(). toLowerCase().trim().toC ...

  8. Java api 入门教程 之 JAVA的String 类

    1.String对象的初始化 由于String对象特别常用,所以在对String对象进行初始化时,Java提供了一种简化的特殊语法,格式如下: String s = “abc”; s = “Java语 ...

  9. String类replaceAll方法正则替换深入分析

    作者网址: https://my.oschina.net/shipley/blog/98973 背景:      前几天有人发了一个关于下面问题的贴,对这个有点好奇,故花时间做了点研究.       ...

随机推荐

  1. UITextField设置leftView的Insets

    Insets就是css中的padding 我们给UITextField设置了leftView,目的是在文本输入框左側显示一个图标.可是在ios7里,这个图标会紧紧地挨着TextField的左边框,非常 ...

  2. Tomcat 8(十)HTTP/AJP Connector、Bio/Nio/Apr性能对照

    Tomcat 8(七)解读Bootstrap介绍过,Connector初始化/启动的时候,将初始化/启动内部的ProtocolHandler.事实上ProtocolHandler仅仅是个接口 Prot ...

  3. WPF3D绘图的基础

    原文:WPF3D绘图的基础 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/details/69487096 ...

  4. 楼塔当天领袖acm心理(作为励志使用)

    楼主个人博客:吉尔博客 假期空闲的时候使用.这些年来GCJ.ACM,TopCoder 的一个号码的一重要的比赛的参与 回顾.GCJ2006 的回顾,今天时间上更早一些吧,我如今还清晰记得3 年 前.我 ...

  5. Linux 下非 root 用户安装 theano(配置 GPU)

    非 root 用户,安装 Python 第三方的包,尤其像 theano,存在大量的依赖项,存在的主要问题,是安装各个包时的权限问题.所幸,存在这样一个集成工具,叫 anaconda,其已经内置了许多 ...

  6. linux_ linux下查看最消耗CPU、内存的进程 20

    1.CPU占用最多的前10个进程: ps auxw|head -1;ps auxw|sort -rn -k3|head -10 2.内存消耗最多的前10个进程 ps auxw|head -1;ps a ...

  7. Binding的三种方式

    1 Text="{Binding Name}" Name为后台的属性 2 Text="{Binding ElementName=XXX,Path=A.B.C.D….}&q ...

  8. WPF DataTemplateSelector的使用

    <Window x:Class="CollectionBinding.MainWindow"        xmlns="http://schemas.micros ...

  9. glibc_error reporting

    很多GNU C库里的函数都会侦测并报告错误条件.我们的程序需要检测这些错误条件.比如:我们打开一个输入文件时需要判断该文件是否正确的打开.如果没有正确打开,我们需要打印错误或者采取其他正确的方式.为了 ...

  10. qt下的时钟程序(简单美丽,继承自QWidget的Clock,用timer调用update刷新,然后使用paintEvent作画就行了,超详细中文注释)good

    最近抽空又看了下qt,发现用它来实现一些东西真的很容易比如下面这个例子,绘制了个圆形的时钟,但代码却清晰易懂[例子源自奇趣科技提供的例子]因为清晰,所以就只写注释了,吼吼其实也就这么几行代码头文件 / ...