封装,继承,多态;
`继承:让某个类型的对象获得另一个类型的对象的属性的方法。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。` 封装:隐藏部分对象的属性和实现细节,对数据的访问只能通过外公开的接口。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。 多态:对于同一个行为,不同的子类对象具有不同的表现形式。多态存在的3个条件:1)继承;2)重写;3)父类引用指向子类对象。 public class Animal { // 动物 public void sleep() { System.out.println("躺着睡"); } } class Horse extends Animal { // 马 是一种动物 @Override public void sleep() { System.out.println("站着睡"); } } class Cat extends Animal { // 猫 是一种动物 private int age; public int getAge() { return age + 1; } @Override public void sleep() { System.out.println("四脚朝天的睡"); } } 在这个例子中: House 和 Cat 都是 Animal,所以他们都继承了 Animal,同时也从 Animal 继承了 sleep 这个行为。 但是针对 sleep 这个行为,Horse 和 Cat 进行了重写,有了不同的表现形式(实现),这个我们称为多态。 在 Cat 里,将 age 属性定义为 private,外界无法直接访问,要获取 Cat 的 age 信息只能通过 getAge 方法,从而对外隐藏了 age 属性,这个就叫做封装。当然,这边 age 只是个例子,实际使用中可能是一个复杂很多的对象。
// 代码块1 short s1 = 1; s1 = s1 + 1; 代码块1编译报错,错误原因是:不兼容的类型: 从int转换到short可能会有损失”。 // 代码块2 short s1 = 1; s1 += 1; 代码块2正常编译和执行。 public class com.joonwhee.open.demo.Convert { public com.joonwhee.open.demo.Convert(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: iconst_1 // 将int类型值1入(操作数)栈 1: istore_1 // 将栈顶int类型值保存到局部变量1中 2: iload_1 // 从局部变量1中装载int类型值入栈 3: iconst_1 // 将int类型值1入栈 4: iadd // 将栈顶两int类型数相加,结果入栈 5: i2s // 将栈顶int类型值截断成short类型值,后带符号扩展成int类型值入栈。 6: istore_1 // 将栈顶int类型值保存到局部变量1中 7: return } 可以看到字节码中包含了 i2s 指令,该指令用于将 int 转成 short。i2s 是 int to short 的缩写。 其实,s1 += 1 相当于 s1 = (short)(s1 + 1),有兴趣的可以自己编译下这两行代码的字节码,你会发现是一摸一样的。
下面先介绍Integer和Int的区别:
2、Integer 类和 int 的区别 ①、Integer 是 int 包装类,int 是八大基本数据类型之一(byte,char,short,int,long,float,double,boolean)
②、Integer 是类,默认值为null,int是基本数据类型,默认值为0;
③、Integer 表示的是对象,用一个引用指向这个对象,而int是基本数据类型,直接存储数值。
回到顶部 3、Integer 的自动拆箱和装箱 自动拆箱和自动装箱是 JDK1.5 以后才有的功能,也就是java当中众多的语法糖之一,它的执行是在编译期,会根据代码的语法,在生成class文件的时候,决定是否进行拆箱和装箱动作。
①、自动装箱 一般我们创建一个类的时候是通过new关键字,比如:
Object obj = new Object();
但是对于 Integer 类,我们却可以这样:
Integer a = 128;
为什么可以这样,通过反编译工具,我们可以看到,生成的class文件是:
Integer a = Integer.valueOf(128);
这就是基本数据类型的自动装箱,128是基本数据类型,然后被解析成Integer类。
②、自动拆箱 我们将 Integer 类表示的数据赋值给基本数据类型int,就执行了自动拆箱。
Integer a = new Integer(128); int m = a;
反编译生成的class文件:
Integer a = new Integer(128); int m = a.intValue();
简单来讲:自动装箱就是Integer.valueOf(int i);自动拆箱就是 i.intValue();
回到顶部
public static void main(String[] args) { Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150; System. out.println( f1 == f2); //true System. out.println( f3 == f4); //false
public static void main(String[] args) { Integer i = 10; Integer j = 10; System.out.println(i == j); 第一个打印结果为 true 对于 i == j ,我们知道这是两个Integer类,他们比较应该是用equals,这里用==比较的是地址,那么结果肯定为false,但是实际上结果为true,这是为什么? 我们进入到Integer 类的valueOf()方法: 分析源码我们可以知道在 i >= -128 并且 i <= 127 的时候,第一次声明会将 i 的值放入缓存中,第二次直接取缓存里面的数据,而不是重新创建一个Ingeter 对象。那么第一个打印结果因为 i = 10 在缓存表示范围内,所以为 true。 Integer a = 128; Integer b = 128; System.out.println(a == b); ②、第二个打印结果为 false 从上面的分析我们知道,128是不在-128到127之间的,所以第一次创建对象的时候没有缓存,第二次创建了一个新的Integer对象。故打印结果为false int k = 10; System.out.println(k == i); ③、第三个打印结果为 true Integer 的自动拆箱功能,也就是比较两个基本数据类型,结果当然为true int kk = 128; System.out.println(kk == a); ③、第三个打印结果为 true Integer 的自动拆箱功能,也就是比较两个基本数据类型,结果当然为true Integer m = new Integer(10); Integer n = new Integer(10); System.out.println(m == n); ③、第三个打印结果为 true Integer 的自动拆箱功能,也就是比较两个基本数据类型,结果当然为true }
2 << 3。
进阶:通常情况下,可以认为位运算是性能最高的。但是,其实编译器现在已经“非常聪明了”,很多指令编译器都能自己做优化。所以在实际实用中,我们无需特意去追求实用位运算,这样不仅会导致代码可读性很差,而且某些自作聪明的优化反而会误导编译器,使得编译器无法进行更好的优化。
这可能就是所谓的“猪队友”吧。