Java面试题汇总 | 基础知识第七章

内部类相关,看程序说出运行结果?

public class Outer{
    private int age =12;
    class Inner{
        private int age =13;
        public void print(){
            int age =14; 
            System.out.println("局部变量:"+ age); 
            System.out.println("内部类变量:"+this.age); 
            System.out.println("外部类变量:"+Outer.this.age);
            }
    }
    public static void main(String[] args){ 
        Outer.Inner in = new Outer().new Inner(); 
        in.print();
    }
}
运行结果:
局部变量:14
内部类变量:13
外部类变量:12
解析 :这段代码演示了局部变量、内部类变量和外部类变量之间的区别和联系。局部变量只在方法内部有效,内部类变量只能被内部类的方法访问,而外部类变量可以被外部类及其内部类访问。在此例中,Inner类通过this关键字访问了其内部的age变量,而Outer类通过Outer.this关键字访问了其外部的age变量。

重写与重载

构造器(constructor)是否可被重写(override)?

构造器不能被继承,因此不能被重写,但可以被重载。

重载(Overload)和重写(Override)的区别?

方法的重载和重写都是实现多态的方式,区别在于方法重载实现的是编译时的多态性,而方法重写实现的是运行时的多态性。

重载的方法能否根据其返回类型进行区分?

重载:发生在同一个类中,方法名相同,参数列表不同(参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分。
重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则); 如果父类方法访问修饰符为private则子类中就不是重写。
加餐小tips:
        上文中 “如果父类方法访问修饰符为private则子类中就不是重写” 这句话该如何理解?如果在子类中定义了一个与父类中private方法具有相同名称、返回类型和参数列表的方法,那这并不是重写父类的private方法,而是另一个概念: 隐式覆盖(implicitly override)。Java 的方法重写规则是基于方法名称、返回类型和参数列表的匹配来进行的,与访问修饰符无关。所以当子类对象调用该方法时,实际上执行的是子类中的方法代码。
         里氏代换原则(Liskov Substitution Principle, LSP)是面向对象设计中的一项基本原则,它属于面向对象设计十原则之一:子类对象应当能够替换基类对象,而且替换后不会产生任何副作用。也就是说,如果一个程序中使用的是基类对象,那么在替换为子类对象后,程序的行为不应该受到影响。这个原则保证了继承关系的清晰和合理,是面向对象设计中实现“开闭原则”和“多态性”的基础。

对象相等判断

== 和 equals 的区别是什么?

== : 判断两个对象的内存地址是否相等。即,判断两个对象是不是同一对象。
        (基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)
equals() : 判断两个对象是否相等。但它一般有两种使用情况:
         情况1:类没有重写 equals() 方法。
                     则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
        情况2:类重写了 equals() 方法。
                     一般,我们都重写 equals() 方法来比较两个对象的内容相等。
示例代码如下 :
public class test{
    public static void main(String[] args){ 
        String a = new String("ab");// a 为一个引用
        String b = new String("ab");// b为另一个引用,二者内容一样 
        String aa = "ab";//存储在常量池中 
        String bb = "ab";//从常量池中查找
        if(aa == bb){
            System.out.println("aa == bb");//true
        }
        if(a == b){
            System.out.println("a == b");//false
        }
        if(a.equals(b)){
            System.out.println("aEQb");//true
        }
        if(42==42.0){
            System.out.println("true");//true
        }
    }
}
说明:
        String中的equals方法默认是被重写过的,因此object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。
加餐小tips:
        在创建String对象时需要注意,每次创建字符串,JVM都会在字符串常量池中查找是否已存在相同的字符串。如果存在,则直接返回该字符串对象以节省资源。如果在不同的地方使用相同的字符串常量,即使看起来创建了多个String对象,实际上在内存中可能只存在一个该字符串对象的原因。

hashCode 与 equals

hashCode()介绍

        hashCode() 的作用是获取哈希码,也称为散列码;它返回一个int整数,作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。

HashSet 如何检查重复?

         当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较。如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。

hashCode()与equals()的易混点

        如果两个对象相等,则hashcode一定也是相同的
        两个对象相等,对两个对象分别调用equals方法都返回true
        两个对象有相同的hashcode值,它们也不一定相等
        因此,若equals 方法被覆盖,则 hashCode 方法也必须被覆盖
        hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。

对象相等与指向他们的引用相等,两者有什么不同?

        对象相等 比较的是内存中存放的内容是否相等,而 引用相等 比较的是他们指向的内存地址是否相等。

值传递

当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

        值传递。Java 语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变不会影响到调用者。
  • 29
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值