()

1.JDK和JRE的区别

对比项 JDK JRE
名称释义 Java Development Kit Java Runtime Enviroment
开发环境工具包,包含了各种类库和工具 运行环境
面向对象 开发人员 使用人员
细节对比 jdk/jre/bin中client和server文件夹下都包含一个jvm.dll jre中只有server下面的jvm.dll
安装使用 配置环境变量后使用的javac,jdk 如果同时安装了jre和jdk使用的java要看环境变量中的配置顺序
  • 如果一台电脑安装两套以上的JRE,谁来决定呢?

    这个重大任务就落在java.exe身上。Java.exe的工作就是找到合适的JRE来运行Java程序。 Java.exe依照底下的顺序来查找JRE:自己的目录下有没有JRE;父目录有没有JRE;查询注册表: [HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment] 所以java.exe的运行结果与你的电脑里面哪个JRE被执行有很大的关系。

2.equals和==的区别

比较对象方法比较原则
基本类型==比较值是否相等
equals比较值是否相等
引用类型==比较引用是否相等
equals默认情况下使用 == 比较,若重写了equals方法,使用重写后的方法
深入 String重写了Object的equals方法,把引用比较改为了值比较,故两个值同 string的 equals 结果为true
  1. 对象 hashCode() 与 equals() 是否对等: hashCode()相等 是否 一定 equals()为 true

在JAVA中所有类都是Object类的子类, 在实际的实现中可以重写对应的方法,故不一定对等 例如 两个String 对象的hashCode可能一样 但实际 equals() = false

HashSet 使用HashMap 将要保存的元素作为key,PRESENT 作为键值对put 到map中
private static final Object PRESENT = new Object();
即使用要放入的元素 的 hashCode方法作重复校验,使用hashMap的put方法,默认情况下会更新值,但不会更新key, 
所有当我们要实现自定义 Class 去重, 且保留最先进入的元素可以用hashset, 同时重写 hashCode()方法

例如

public class CaseTest
{
    class DemoSet{
        String id;
        int name;

        public DemoSet(String id, int name)
        {
            this.id = id;
            this.name = name;
        }

        @Override
        public int hashCode()
        {
            int result = 17;
            result = 31 * result + (id == null ? 0 : id.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj){
            if(obj instanceof DemoSet){
                DemoSet ds = (DemoSet) obj;
                if(ds.id.equals(this.id)){ // ds.id == this.id
                    return true;
                }
            }
            return false;
        }
        @Override
        public String toString(){
            return String.format("{id:%s,name:%d}",id,name);
        }
    }
    @Test
    public void testSet(){
        HashSet set = new HashSet();
        Set<DemoSet> demoSets = Sets.newConcurrentHashSet();
        demoSets.add(new DemoSet("1",1));

        Set<DemoSet> demoSets2 = Sets.newConcurrentHashSet();
        demoSets2.add(new DemoSet("1",2));

        demoSets.addAll(demoSets2);

        System.out.println(demoSets);
    }
}
最终列表之后保留 1,1 注意字符串 == 比较引用
  1. final 修饰符的作用
作用 特性
最终类,不可继承
方法 不可重写
变量 常量,必须被初始化,初始化值不可修改
只要在对象构造完成之前初始化即可

引申 为什么匿名内部类参数必须为final类型 局部内部类能访问方法中的所有的局部变量,问题在于 局部变量的生命周期与局部内部类的对象的生命周期的不一致性

1.  设方法f被调用,从而在它的调用栈中生成了变量i,此时产生了一个局部内部类对象inner_object,它访问了该局部变量i.
当方法f()运行结束后,局部变量i就已死亡了,不存在了
但:局部内部类对象inner_object还可能一直存在(只能没有人再引用该对象时,它才会死亡),它不会随着方法f()运行结束死亡.
这时:出现了一个"荒唐"结果:局部内部类对象 inner_object要访问一个已不存在的局部变量i!
2.  当变量是final时,通过将final局部变量"复制"一份,复制品直接作为局部内部中的数据成员.这样:当局部内部类访问局部变量 时,其实真正访问的是这个局部变量的"复制品"(即:这个复制品就代表了那个局部变量).因此:当运行栈中的真正的局部变量死亡时,局部内部类对象仍可以 访问局部变量(其实访问的是"复制品"),给人的感觉:好像是局部变量的"生命期"延长了.
3.  那么:核心的问题是:怎么才能使得:访问"复制品"与访问真正的原始的局部变量,其语义效果是一样的呢?
4.  当变量是final时,若是基本数据类型,由于其值不变,因而:其复制品与原始的量是一样.语义效果相同.(若:不是final,就无法保证:复制品与原始变量保持一致了,因为:在方法中改的是原始变量,而局部内部类中改的是复制品)
5.  当变量是final时,若是引用类型,由于其引用值不变(即:永远指向同一个对象),因而:其复制品与原始的引用变量一样,永远指向同一个对象(由于是 final,从而保证:只能指向这个对象,再不能指向其它对象),达到:局部内部类中访问的复制品与方法代码中访问的原始对象,永远都是同一个即:语义效 果是一样的.否则:当方法中改原始变量,而局部内部类中改复制品时,就无法保证:复制品与原始变量保持一致了(因此:它们原本就应该是同一个变量.) 
from https://feiyeguohai.iteye.com/blog/1500108
  1. java中Math函数易错知识

    Math.round(-1.5) = -1

     * <ul><li>If the argument is NaN, the result is 0.
     * <li>If the argument is negative infinity or any value less than or
     * equal to the value of {@code Integer.MIN_VALUE}, the result is
     * equal to the value of {@code Integer.MIN_VALUE}.
     * <li>If the argument is positive infinity or any value greater than or
     * equal to the value of {@code Integer.MAX_VALUE}, the result is
     * equal to the value of {@code Integer.MAX_VALUE}.</ul>

    距离一致,取较大的值 Math.rint(-10.5) = -10.0 Math.rint(-11.5) = -12.0

    StrictMath.rint(a)
    x取整为它最接近的整数,如果x与两个整数的距离相等,则返回其中为偶数的那一个

    6.java的基本数据类型 java中有8中基本类型 byte boolean char short int float long double

基本类型 字节长度 默认值
byte 1 0
short 2 0
int 4 0
long 8 0L
float 4 0.0f
double 8 0.0d
char 2 ‘\u0000’
boolean 1 false
  1. Java中字符串操作类,String StringBuffer StringBuilder 对比
操作类 特点
String 声明不可变对象,每次操作产生新的对象,修改指针指向
StringBuffer 线程安全,每次可操作原有对象
StringBuilder 线程不安全,更高性能,操作原有对象

StringBUffer 在方法上使用 synchronized关键字 保证线程安全