跟着GitHub上的 27天成为java大神 项目学习Java。
损失精度
1 | 面试题: |
第一个是存在问题的,java默认类型是int, s = s+1
里的1就是int类型的,所以等号右边的s+1会被转化成int类型,而一个int类型的值要赋值给short类型的变量,就会报错。
1 | s += 1; |
逻辑右移与算数右移
1 | >> //算数右移,最高位补符号位 |
1 | -1 原码:1000 0001 |
打印数组名
1 | public static void main(String[] args) { |
未初始化的数组被编译器初始化为0,打印arr出现字符串**[I@2f92e0f4**其中 [ 代表该数据为数组,I 代表数据类型是int,后面的是地址。
特殊的,如果打印的是一个char数组命,则会直接打印出数组内容
1 | class test01 { |
这是因为方法的重载,public void println(char[] x) 是直接打印出内容,其余几个类型是打印地址。
java中只有值传递
如果想通过方法修改数组可以传递地址,也就是数组名。
this的本质
this的本质:代表方法调用者的地址值
float与long
long类型的数据后面要加上L或l,float类ing的数据后面要加上f或F,因为整数类型默认是int,浮点类型默认是double。
Java中的内存分配
程序在运行时需要在内存分配空间为了提高效率,对空间进行了划分。
- 栈 存储局部变量
- 堆 存储new出来的东西
- 方法区
- 本地方法区
- 寄存器
static
Java中的静态关键字,类中的变量/方法被static修饰,则可以被所有对象共享。并且被static修饰的成员可以直接通过类名进行调用。
1 | class Student{ |
在静态方法中没有this关键字,因为静态是随着类的加载而加载的(存放在堆中的静态区),优先于对象进入内存,而this是随着对象进入内存的,先进内存的不能访问后进内存的,而后进入内存的可以访问先进入内存的。
静态只能访问静态,静态的成员方法只能访问静态成员变量和静态的成员方法,非静态的成员方法则可以访问所有。
变量的就近原则
使用变量的时候会优先找局部范围,如果想直接使用成员变量可以使用this关键字。及承建的成员变量也符合这个规则,如果想使用父类的成员变量可以使用super关键字。
继承
子类会默认调用父类的无参构造方法
1 | class ExtendDemo{ |
上述代码的输出是什么?是666吗,不,是father 666,这是为什么呢????因为在调用子类的构造方法输出666之前先调用了父类的无参构造方法,要想只输出666有两种方法,第一种是清空父类的所有构造方法,如下
1 | class Fu{ |
这样父类会有一个默认的Fu{},没有影响,特别注意的是就算Fu类定义成下面这个样子也是不行的,因为编译器检测到存在构造方法,就不会自动添加一个无参构造方法,这样子类在调用父类的构造方法时就会出错。
1 | class Fu{ |
第二种是使用super关键字
1 | class Fu{ |
super(…)关键字可以访问父类的带参构造方法,this(…)访问本类的构造方法。
方法重载与方法重写
方法重写 override 发生在子类与父类之间,当子类与父类方法声明相同时就发生了方法重写,返回值类型、参数列表不可改变。
**方法重载 overload ** 发生在同一个类中,当方法名相同但是参数列表不相同时就发生了重载,重载可以使用不同的返回值类型。
多态
多态可以理解为一个事物的多种形态,比如水,有固体水、液体水、气体水,可以定义一个水类,固液气采用继承的方式来创建新的类,这样既有了水的共性,又有各自的特性。我上面的表达不就是继承吗?哈,这样说似乎也没什么问题,多态的三个必要条件就是:继承、方法重写、父类指向子类对象。继承是多态的前提。
1 | //父类指向子类对象 |
对于多态成员变量:编译、运行看左边
看左边指的就是左边的 fa
1 | //父类 |
运行结果,也就是左边的Father类中的age
1 | 44 |
对于多态成员方法:编译看左边,运行看右边。
这里的编译,也就是在运行前,我们写出来,编译器就会检测,如果有错误就不能运行
1 | //父类 |
虽然实际运行时使用的是子类的方法,但是在编译阶段,看的左边的父类,父类中没有这个方法,所以直接编译不通过。父类无法调用子类独有的方法,如何解决这个问题?有两种方案,其一是在父类中增加一个空的play方法
1 | //父类 |
其二是引用类型转换
引用类型转换
向上转型(自动转换)
子类向父类转型,可以理解为儿子变为父亲。父类引用指向一个子类对象,就是向上转型
1 | Fteher fa=new Son(); |
父类有很多子类,而子类却只有一个父类,所以向上转型是自动的.
向下转型
父类向子类转型,需要强制转换,也就是指定转换类型。
1 | Father fa=new Son(); |
在完成向下转型后,fa2的变量是子类的,方法是子类与父类的和。
1 | //父类 |
1 | 爸爸吃饭 |