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多态的理解
前提条件:
- 继承 ;
- 重写;
- 父类的引用指向子类。
里氏替代原则就是依靠多态。
核心内容:
- 程序中定义的引用指向子类和通过引用调用的方法,在代码编译时期是不确定的,只有当程序运行时,通过具体的子类对象,调用子类重写方法,这样就不需要修改源代码,让引用绑定到不同的子类实现上,让程序具有多种运行的形态,这就是多态
- 子类的引用由于向上转型,如果子类的方法不是通过父类重写的,则通过引用无法调用该方法。调用子类重写的方法,成为动态连接或动态调用。
- 调用优先级: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
|
什么是内部类?内部类的作用
- 内部类依然是一个独立的类,在编译之后会生成一个独立的.class文件,只是前缀是外部类名$。
- 内部类不能通过普通的方式访问,不能被同包名下其他类访问。
- 内部类仍然属于外部类的一个成员,所以可以自由访问外部类的成员变量,包括private。
- 如果内部类声明为static则只能访问外部类静态成员变量。
- 补充:内部类继承某个类或实现接口,内部类可操作创建外部类对象。所以你可以任务内部类提供某种进入其外部类的窗口。这里就能实现多重继承,内部类可以继承某个类,外部类亦可,而且对内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。虽然接口解决了多重继承的问题,但是内部类也实现了这样的功能。
抽象类的意义。抽象类与接口的应用场景
抽象类的意义:
- 为了提供公共的类型;
- 封装子类中重复的成员变量和方法;
- 抽象的方法,子类可以具有不同的行为;
- 抽象类和接口使得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/
父类的静态方法能否被子类重写
所谓静态就是指:在编译之后所分配的内存会一直存在(不会被回收),直到程序退出内存才会释放这个空间。
静态方法属于类不属于对象,即使子类和父类的静态方法一样,也不能算是重写,是属于两个类的不同方法,这两个方法在程序运行类加载过程中就已经在内存中创建好,属于两块不同的内存。