• Java面试必会知识点


    1、== 和 equals()比较:

      (1)== 是运算符,equals()是Object中定义的方法;

      (2)== 比较的是 数值 是否相同,基本类型比较数值,引用类型比较对象地址的数值;且变量类型的声明中注意两点,不然编译都不能通过: 

         a. == 两边的类型要么相同,要么存在着继承关系;

         b. == 也可用来比较数组,但数组中的存储类型需保存一致;

        equqls()在Obejct类中默认实现和 == 相同,但实际使用中为了更加实用,通常会重写这个方法,比如在包装类、String、Date类中都是比较保存的值;

        equqls()源代码如下:

        //Object 中equals的实现
        public boolean equals(Object obj) {
            return (this == obj);
        }
    
        //String 类中equals的实现
            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;
        }
    
        //Integer中 equals的实现
        public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }
    View Code

    2、instanceof :

      判断一个对象是否是某个类的实例 或 接口的实现; 当满足右边为对象 实际实例对象的,满足下面任一个时为true;

      (1) 对应的 类或父类;

      (3)实现的接口,或父类实现的接口;

      instanceof 通常用在要进行强制转化前先进行判断;

      注:和==类似,两边的变量类型的声明中注意两点,不然编译都不能通过: 

         a.  两边的类型要么相同,要么存在着继承关系;

         b.  也可用来比较数组,但数组中的存储类型需保存一致;  

    3、理解hashCode 与 equals()的关系:

      hashCode通常被其它类调用,比如在添加元素到Set中,添加到Map中,判断Set 和 Map的key 是否相同;

      在Set的 add()方法中,和Map的 put()方法中,会先判断hashCode()是否相等,再则判断equals()是否相等,若都相等则不添加;若不相等则添加;

      add() 和 put()源码如下:

        // Set 中add 利用了Map的put 来实现
        public boolean add(E e) {
            return map.put(e, PRESENT)==null;
        }
    
        //Map 中 put 的实现
        public V put(K key, V value) {
            if (key == null)
                return putForNullKey(value);
            int hash = hash(key);
            int i = indexFor(hash, table.length);
            for (Entry<K,V> e = table[i]; e != null; e = e.next) {
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                    V oldValue = e.value;
                    e.value = value;
                    e.recordAccess(this);
                    return oldValue;
                }
            }
    
            modCount++;
            addEntry(hash, key, value, i);
            return null;
        }
    View Code

      所以若equals()相等,则需要保证hashCode必须相等,才能使集合正常工作;而hashCode相同,而equals可以不同是很正常的事情,HashMap是一种数组加链表的结构,其中链表即可解决hashCode相同发生碰撞的问题。

    4、Object类中的定义的方法:

      有9种: 集合2、基本2、生命周期2、线程3

      hashCode()

      equals()

      toString()

      getClass() //获取在堆区中的对应的 类的描述对象,对应的Class对象;

      clone()

      finalize()

      wait()、notify()、notifyAll()    

     5、sleep() wait() 区别,及yield()方法;

    (1)所属类:wait()是Object中的方法,使当前线程进行锁池;sleep()是Thread中的静态方法,使当前线程挂起一段时间;

    (2)锁:sleep只是让当前线程让出cpu给其他线程,不会释放对象锁;wait是进入对象的 wait pool池中,会释放对象锁。

    (3)使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 

    1. synchronized(x){ 
      x.notify() 
      //或者wait() 
      }

      两者相同点:都需要捕获InterruptedException异常。

      yield(),Thread的静态方法,短暂让出cpu,让 相同优先级更高优先级 的线程获得运行机会,一般调试时才用。

    6、理解接口 和 继承

      接口有两重意思:a. 一个类提供的public方法,给其它类调用;

              b. interface 声明的接口;

      这里重点说Interface声明的接口:

      接口:接口的本质 是一种规范 和 声明,借助它对外传达一种拥有什么功能的目的;使类与类之间关心接口,而不且关心各自实现,如现实生活中接口一样,只要一个类实现了一个接口,其它类便可依照这个接口做对接即可。

        (如ArrayList 类实现了一个名为RandomAccess的接口,但不包含任何方法,只是标识着它具有快速随机访问的特性)

        使用接口可达到 依赖倒置原则目的;接口使得类与类之间解耦;

        可以实现多接口;

      继承:对外传达一种 is-a,是什么的目的;是类功能和属性的扩展的方法,继承关系的两个类之间有很紧密的关系;

         继承使得代码最大化的复用;

         只能单继承;

    7、为什么String等包装类是不可变量:

      不可变的安全性:大量URL,文件路径,类加载都是依靠String类型的值;

      线程安全:多个线程间不可修改其值肯定是线程安全的;

      满足字符串常量池的实现:多个String可能指向同一个地址,但逻辑上是独立的;

    8、 Java中private方法能重写吗?[转]

    public class A {
        private void print() {
            System.out.println("A");
        }
        public static void main(String[] args) {
            A a = new B();
            a.print();
            B b = new B();
            b.print();
        }
    }
    
    class B extends A {
        public void print() {    
            System.out.println("B");
        }
    }
    
    // 运行结果
    // A
    //
    // B
    View Code

      在Java中,所有的private方法默认是final的,即不可继承的。所以当B继承A时,A的private方法print()不被B继承。

      而B中的public方法print()相当于B添加的一个方法,不属于重写。

    9、Math.round(n) 四舍五入

      Math.round(11.5) 等于多少? Math.round(-11.5)等于多少? 
      答:Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。

    10、Java:对double值进行四舍五入,保留两位小数的几种方法

      http://www.cnblogs.com/nayitian/p/3214178.html

    11、switch case支持的类型:

    switch( expr ){
    
      case value1:
        break;
      
    case value2:     break;
      
    default: }

    其中expr支持:

      1、能自动转化为int的类型(byteshortcharint)

      2、字符串类型(JDK 1.7)

      3、枚举类型

     12、循环中的跳转控制:

    loop1: for (int i = 0; i < 5; i++) {
                loop2: switch (i) {
                case 0:
                    System.out.println("0");
                    break; //退出switch语句
                case 1:
                    System.out.println(1);
                    break loop2; //退出switch语句
                case 3:
                    System.out.println(2);
                    break loop1; //退出for循环
                default:
                    System.out.println("default");
                    continue loop1; //结束本次循环,执行下一次循环。这里和没有这个语句效果一样
                }
           System.out.println("i:" + i); }
    另注:continue用在for循环中,
    结束本次循环会执行i++
    
    

    13、方法重载需满足:

      1、方法名相同;

      2、参数的类型 或 个数不同;

      (返回类型可以不同,方法修饰符可以不同)

      

      另:普通方法可以和构造方法同名,但不推荐;

    14、方法覆盖:

      A、子类方法的 名称、参数、返回类型 都需要一样;

        编译器在编译时会先检查 方法名,如果相同,这时可能是重载,可能是覆盖,

          如果参数不同,则为重载;

          如果参数相同,则为覆盖,这里返回类型也需要相同,不然编译不通过;(不会存在方法名和参数相同,但返回类型不同的方法)

      B、子类不能缩小父类访问权限

          为什么:因为会与Java多态机制的动态绑定冲突;

      C、子类不能抛出比父类多的异常

          子类抛出的异常要么和父类抛出异常相同,要么抛出的异常是父类抛出异常的子类;

          为什么:同缩小权限,也是和多态机制有关;

      D、子类不能把父类的静态方法覆盖为非静态(静态方法不支持覆盖),子类能隐藏父类的静态方法;

          子类定义的静态方法也必须满足和方法覆盖类似的约束:方法名、参数、返回类型一致;不能缩小权限,增加异常;

          使用时根据类的引用,调用不能的各自的静态方法;

          另:父类的非静态方法不能被覆盖为静态方法;

          

    15、一个文件中的顶层类只能是public或默认访问权限;且public修饰的类只能有一个;

    16、abstract抽象类、抽象方法

      A、抽象类中可以没有抽象方法;包含抽象方法的类需声明为抽象类;

      B、不能与static final private连用;

      C、抽象类中可以有非抽象的构造方法;

    17、接口

      接口中的属性的默认是public static final 、方法是public abstract;

      JDK 1.8前,接口只能包含抽象方法。1.8后,为了提高代码的可重用性,允许在接口中定义 默认方法 和 静态方法。默认方法使用default声明;实现接口的类可访问默认方法,也可以实现它。

    18、final变量初始化

      可用来修饰 类、方法、变量(静态变量、成员变量、局部变量)

      在修饰变量时需显示初始化:

        静态变量:定义时 或 静态代码块中初始化;

        实例变量:定义时 或 构造方法中初始化;

    19、static

      构造方法用来初始化对象,static代码块用来初始化类;

    20、excepiton 异常

       A、try 后面可以有零个或多个catch,也可以是零个或一个finally;但try代码块不能单独存在(try后可只跟finally);

       B、JDK 1.7后 catch可同时捕捉多个异常:    

    try{
    }catch(FileNotFoundException | InterruptedIOException ex2){
    }

       B、finally唯一不被执行的情况是调用了System.exit()方法,使整个进程终止;

       C、若在try或catch 执行 return语句,则也会先执行finally,再return;  

    // a. finally虽在return前执行,但不能改变返回变量的值:
    int a = 0;
    try{
        return a;
    }finally{
        a=1; //返回的还是0
    }
    // b. 建议不要在finally代码块中使用return语句:
        1、它会覆盖try或catch代码块中的return语句
        2、异常的丢失
    
    1
    try{
        return methodA(money);
    }catch(SomeException e){
        return -100;
    }finally{
        return 100; //会覆盖-100
    }
    
    2
    try{
        return methodA(money);
    }catch (SomeException){
        throw new Exception("catch wrong");
    }finally{
        return 100; // catch中的抛出异常失效    
    }

    21、Java中是值传递还是引用传递?

    java中只存在值传递,只存在值传递!!! 然而我们经常看到对于对象(数组,类,接口)的传递似乎有点像引用传递,可以改变对象中某个属性的值。但是不要被这个假象所蒙蔽,实际上这个传入函数的值是对象引用的拷贝,即传递的是引用的地址值,所以还是按值传递。

    注:C++才有引用传递,用&表示。

    22、内部类

    主要有:实例内部类、静态内部类、局部内部类

    实例内部类、局部内部类 均可访问外部类的所有成员,包括private;

    局部内部类可以访问:a. 方法中final修饰的变量;b. 没有修改过值的变量;

    另还有 匿名内部类,可以继承类或实现接口;约束和实例、局部内部类相同;

    内部类的用途:a. 封装类型;b. 直接访问外部类成员;c. 回调;

    23、数组:

    // 普通数组声明
      int scores[];
          int[] scores;
    
      String names[]
          String[] names;
        
         //二维数组声明
         int x[][]; int [][]x; int []x[];
    
        //声明时不用指明长度
        int x[5] //编译不通过
    
    //创建数组对象, new的过程会自己设定默认值
        int[] scores = new int[10];
    
    //初始化方式
        a.利用for来设定
        b.直接在创建时赋值, 大括号 加 逗号;
        int a[] = {4,5,6};
        int a[] = new int[]{4,5,6};
        char ch[] = {'a' , 'b' , 'c' };
        String str[] = {"12" , 34"" , "56" };

    实用类 Arrays

      提供 equal() sort() arraycopy() fill() asList()

    变长入参

      public static int max(int... datas){
    
        //以数组方式访问datas
        if(datas.length == 0)
          return -1;
      }
  • 相关阅读:
    Codeforces 101487E
    算法笔记--2-sat
    算法笔记--图的存储之链式前向星
    算法笔记--强连通分量分解
    Uva 11995 I Can Guess the Data Structure!
    算法笔记--米勒-罗宾素数测试
    HDU 5183 Negative and Positive (NP)
    算法笔记--快读(输入外挂)模板
    POJ 3258 River Hopscotch
    HDU 2289 Cup
  • 原文地址:https://www.cnblogs.com/mzzcy/p/7053242.html
Copyright © 2020-2023  润新知