目录
1.String s=new String(“xyz“) 创建了几个对象?
2.Java 中的 switch 语句只能是int,枚举类型吗?
3.Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
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.子类会继承所有属性和方法,除私有之外。所以子类加载时,会先加载父类的属性和方法,再加载子类的。
之前学习多态时:方法是编译看左,运行看右。但是子类继承父类的静态方法,使用多态不会把父类的方法重写,覆盖掉。因为父类的静态方法跟随着父类的加载而被加载完成,所以调用的是父类的静态方法,而不是子类的静态方法。
运行结果: