Java之问题总结(常用API和集合):

目录

1.String s=new String(“xyz“) 创建了几个对象?

2.Java 中的 switch 语句只能是int,枚举类型吗?

3.Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?

4.错题1:不产生编译错误的是:

5.错题2:有编译错误的是

6. 为什么Hashse存放自定义类型元素时,要重写对象中的hashCode和equals方法,才能保证元素唯一。

7.new一个对象,传给父类类型,调用子类的静态方法时,为什么调用的是却是父类的静态方法

1.String s=new String(“xyz“) 创建了几个对象?

在String池中中找到xyz,不创建对象,否则创建一个对象。

new关键字,创建一个String类对象。

扫描二维码关注公众号,回复: 15643773 查看本文章

自己的理解以及查阅部分资料(不知道对不对,如有错误,还请指正)。

2.Java 中的 switch 语句只能适用于int,枚举类型吗?

    2.1  switch的使用:

switch语句适用于对多个整型数值(包括负数)进行匹配判断,从而实现条件的分支控制。

判断为真,则找到对应的case值,执行对应的代码

   与if语句不同的是:

1.if语句是根据后面的表达式判断的,所以这个判断可以任意写。

2.switch语句是单纯做  “表达式==数值”判断,只是一个整数的判断。

    2.2   switch实现原理:

程序最终是一条条语句,Cpu中有一个指令指示器,CPU根据指令器加载执行指令,完成一条指令操作时,指令器会自动指向下一条指令,有些指令会修改指令指示器的值,使CPU跳转到其他的地方去执行,这种指令叫做跳转指令。跳转指令分为两种:一种条件跳转语句,满足跳转条件,则跳转。另一种是无条件跳转,直接跳转执行该指令。

    与之对应放到switch语句中:

switch语句编译成class文件,当分支语句较少时,则会直接使用条件跳转语句,条件满足执行case语句。分支语句较多时,避免效率低,使用跳转表——映射表,存储对应值与之对应的地址。根据该值找到跳转地址。

   2.3  解决:

short,byte,char都可以,因为他们会自动转型为int,但是long不行,因为long超过了跳转表的范围,String类型可以使用hashcode转换为对应的整数。

所以:Byte、Short、Character、Integer,还有从Java5开始支持的枚举类型和Java7开始支持的String类。都适用于switch语句。

3.Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?

Overload(重载):重载是方法层面上的多态体现,在同一个类中,只要方法名相同,参数列表(参数顺序,参数个数,参数类型)不同,构成重载。

Override(重写):重写是父类与子类层面上的多态。在子类中重新写执行语句,方法声明和父类的必须一样。

overload和改变返回值类型没有太大的关系,可以改变。

4.错题1:

以下选项可替换题目中//add code here而不产生编译错误的是(A D    )。(选择二项)

public abstract class MyClass{

public int constInt=5;

//add code here

public void method( ){

}

}

A

public abstract void method(int a);

B.

constInt =constInt+5;

C.

public int method( );

D.

public abstract void anotherMethod( );

分析:

1.方法重载只需要参数列表(参数个数,参数类型,参数顺序)不同就可以了,跟返回值类型,以及是否添加abstract等关键字无关。

2.属性定义和赋值可以写在方法外,但是,属性的运算等其他操作要写在方法内。

class MyClass {
    int[] a=new int[10];
    a[2]=a[2]+2;
    public void eat(){
        int constInt=5;
        constInt =constInt+5;
    }

    public void method( ){
    }

方法外的那层代码就会报错,而在内部的就不会。

5.错题2:

已知类A、B、C和接口D的定义如下:

    public class A{…}

    public class B extends A implements D {…}

    public class C extends A {…}

    public interface D {…}

    变量a、b、c、d的定义如下:

    A a = new A();  B b = new B();  

    C c = new C();  D d = null;

    则下列语句会有编译错误的是( D )。

A.   

  a = b;

B.   

  d = b;  

C.   

  d = (D)a;

D.   

  c = (C)b; 猫不能转为狗)

考查的是三大特性之一的多态,关于多态我们需要记住这几点关键的部分:

   1.向上转型,向下转型

   2.子类对象传给父类类型,是为多态。

   3.instaceof关键字

在这道题中,同一等级的对象不能强转——猫不能转成狗

6. 为什么Hashse存放自定义类型元素时,要重写对象中的hashCode和equals方法,才能保证元素唯一。

 Hashset是如何判断元素相同呢?

  1.先通过hashcode计算出元素的哈希值,如果有已经存在的hashcode与它相同,那么视为相同元素,执行第二步操作。如果不相同,说明元素不相同,添加到集合中。

  2.当哈希值相同时,调用equals方法比较两个元素属性是否相同,相同不添加元素,不相同添加到集合中。

看这个例子:

public class HashsetTest {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add(new Student("小李"));
        hashSet.add(new Student("小李"));
        int a=hashSet.size();
        System.out.println("元素个数为:"+a);
    }
}
class Student{
    int id;
    String name;
}

 输出结果:

说明两个元素都添加进去了。为什么呢?

  回到hashset是如何判断元素相同的,首先我是分别传入两个相同属性的对象——对象相同,地址值不同。所以hashcode不同,判断机制就会返回false判断他们两个不同,这样集合中就存入了两个同一类的相同对象。所以我们要重写hashcode方法,把判断指向他的属性(名字),这个时候就是获取到属性值name对应的hashcode,而不是地址值的hashcode。

@Override
    public int hashCode() {
        return this.hash(name);
    }

由于返回的true,进入第二步调用equals方法,我们自定义的类中是没有equals方法的,调用的是Objects类中的equals方法,而它比较的也是地址值,所以我们也要重写equals方法。

 @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Student)) return false;
        Student student = (Student) o;
        return name.equals(student.name);
    }

重写完之后,比较的是对应的属性的内容。最终才判断是否是同一个元素。

 注意点:

Object里的equals比较的是对象的地址,hashcode也是根据地址计算的。重写之后hashcode比较的是属性,equals比较的也是属性。

7.new一个对象,传给父类类型,调用子类的静态方法时,为什么调用的是却是父类的静态方法

  先看代码:

public class Person {
    public static void main(String[] args) {
        //编译看左边
        PersonFather person=new Personson();
        person.scrore=100;
        person.eat();
        person.sleep();
        System.out.println(person.scrore+" ,");
    }

}
class PersonFather{
    String name="父类";
    int scrore=1000;
    public static void eat(){
        System.out.println("我是父类的静态吃方法");
    }
    public void sleep(){
        System.out.println("我是父类的睡觉静态方法");
    }
}
class Personson extends PersonFather{
    String name="子类";
    int score=10;
    public static void eat(){
        System.out.println("我是子类的静态吃方法");
    }
    public void sleep(){
        System.out.println("我是子类的睡觉静态方法");
    }

}

知识点基础:

  1.stastic修饰的成员方法和变量 被加载时,是跟着类加载而加载。他的生命周期和类相同。

  2.子类会继承所有属性和方法,除私有之外。所以子类加载时,会先加载父类的属性和方法,再加载子类的。

之前学习多态时:方法是编译看左,运行看右。但是子类继承父类的静态方法,使用多态不会把父类的方法重写,覆盖掉。因为父类的静态方法跟随着父类的加载而被加载完成,所以调用的是父类的静态方法,而不是子类的静态方法。

运行结果:

猜你喜欢

转载自blog.csdn.net/qq_50692350/article/details/126268591