Java基础篇

java中==和equals和hashCode的区别

  • ==:运算符,比较变量是否相等,或者两个对象的地址值是否相同。
  • equals是Object类的方法,方法默认比较两对象在内存中的地址值是否相等。
  • hashcode也是Object类的方法,返回的是离散int型整数。在集合的操作中,可提高查询速度。

三者区别:根据java的数据类型,如果是基本数据类型进行比较,使用== 运算符比较两者间的值。如果是复合数据类型(对象)使用==比较的为地址值,使用equels又分两种,第一种如String,Integer,Date等重写equels方法,有其自身的比较方式,如String遍历char类型做比较:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = count;
if (n == anotherString.count) {
int i = 0;
while (n-- != 0) {
if (charAt(i) != anotherString.charAt(i))
return false;
i++;
}
return true;
}
}
return false;
}

第二种不覆盖equels方法则同== 相同,比较的为内存中的地址值。

如果equals方法相等,两对象hashCode方法产生相等的int结果,不相等则不一定产生相同结果。

集合的操作规则:对象放入结合中,先比较hashCode值,不同则放入,相同则通过equals方法判断与集合中任意一个对象是否相等,不相等则放入。get去元素时,HashMap也先调key.hashCode()算出数组下标,再看equals()true则返回。

具体参考EffectiveJava第8条。

int、char、long各占多少字节数

int 4 short 2 long 8 byte 1

float 4 double 8

char 2

boolean 1

1byte = 8bit

int与integer的区别

Integer是int的包装类,int可直接赋值,存放常量池中,默认值为0,Integer必须实例化后才能使用,存放在堆内存中,默认值当然是null。

还有自动拆装箱和Integer缓冲区问题:

举例说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Integer a = new Integer(100);
Integer b = new Integer(100);
System.out.print(a == b); // 不同对象地址值肯定不相等
int c = 100;
System.out.print(a == c); // true a自动拆包装为int
Integer d = 100;
Integer e = 100;
System.out.print(a == d); // false 非new的Integer在常量池中
System.out.print(d == e); // true
Integer i = 128;
Integer j = 128;
System.out.print(i == j); // false Integer i = 100;时,会翻译成为Integer i = Integer.valueOf(100);
// 在 -128 到 127之间就不需要new
public static Integer valueOf(int i){
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}

对java多态的理解

前提条件:

  1. 继承 ;
  2. 重写;
  3. 父类的引用指向子类。

里氏替代原则就是依靠多态。

核心内容:

  1. 程序中定义的引用指向子类和通过引用调用的方法,在代码编译时期是不确定的,只有当程序运行时,通过具体的子类对象,调用子类重写方法,这样就不需要修改源代码,让引用绑定到不同的子类实现上,让程序具有多种运行的形态,这就是多态
  2. 子类的引用由于向上转型,如果子类的方法不是通过父类重写的,则通过引用无法调用该方法。调用子类重写的方法,成为动态连接或动态调用。
  3. 调用优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。即先查this对象的父类,没有就重头再查参数的父类

多态的优点:
可替换,可扩充,接口性,灵活操作,简化程序

经典案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
public class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
public class C extends B{
}
public class D extends B{
}
public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
/*4--B and A
首先a2是A引用,B实例,调用show(B b)方法,
此方法在父类A中没有定义,所以B中方法show(B b)
不会调用(多态必须父类中已定义该方法,
再按优先级为:this.show(O)、super.show(O)、
this.show((super)O)、super.show((super)O),
即先查this对象的父类,没有重头再查参数的父类。
查找super.show((super)O)时,B中没有,再向上,
找到A中show(A a),因此执行。*/
System.out.println("5--" + a2.show(c)); //同上
System.out.println("6--" + a2.show(d)); //A and D .查找B中没有show(D d)方法,再查A中,有,执行。
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c)); //B and B .
System.out.println("9--" + b.show(d));
}
}
运行结果:
[java] view plain copy
1--A and A
2--A and A
3--A and D
4--B and A
5--B and A
6--A and D
7--B and B
8--B and B
9--A and D

什么是内部类?内部类的作用

  1. 内部类依然是一个独立的类,在编译之后会生成一个独立的.class文件,只是前缀是外部类名$。
  2. 内部类不能通过普通的方式访问,不能被同包名下其他类访问。
  3. 内部类仍然属于外部类的一个成员,所以可以自由访问外部类的成员变量,包括private。
  4. 如果内部类声明为static则只能访问外部类静态成员变量。
  5. 补充:内部类继承某个类或实现接口,内部类可操作创建外部类对象。所以你可以任务内部类提供某种进入其外部类的窗口。这里就能实现多重继承,内部类可以继承某个类,外部类亦可,而且对内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。虽然接口解决了多重继承的问题,但是内部类也实现了这样的功能。

抽象类的意义。抽象类与接口的应用场景

抽象类的意义:

  1. 为了提供公共的类型;
  2. 封装子类中重复的成员变量和方法;
  3. 抽象的方法,子类可以具有不同的行为;
  4. 抽象类和接口使得java更具强大的面对对象能力。

个人理解:在面向对象的概念中,所有的对象都是通过类描绘的,反之则不是,不是所有的类都是来描绘对象的,如果一个类中没有足够的信息来描绘这个具体对象,这个类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计得出的抽象概念,是对一系列看上去不同但本质上相同的具体概念抽象。

泛型中 extends 和 super 的区别?

https://itimetraveler.github.io/2016/12/27/%E3%80%90Java%E3%80%91%E6%B3%9B%E5%9E%8B%E4%B8%AD%20extends%20%E5%92%8C%20super%20%E7%9A%84%E5%8C%BA%E5%88%AB%EF%BC%9F/

父类的静态方法能否被子类重写

所谓静态就是指:在编译之后所分配的内存会一直存在(不会被回收),直到程序退出内存才会释放这个空间。
静态方法属于类不属于对象,即使子类和父类的静态方法一样,也不能算是重写,是属于两个类的不同方法,这两个方法在程序运行类加载过程中就已经在内存中创建好,属于两块不同的内存。