目录
1、取模
%取模的本质是: a%b --->本质是a-a/b*b
例如: -10%3 其实就是 -10-(-10)/3*3 结果:-1
额外注意的是
-10.5%3 当有小数进行取模的时候 本质是:-10.5-(int)(-10.5)/3*3=-1.5
2、原码 反码 补码
-
二进制的最高为是符号位:0代表正数 1代表负数
-
正数的原码、反码、补码是一样的
-
负数的反码=它的符号位不变,其他位进行取反
-
负数的补码= 反码+1 负数的反码=补码-1
-
0的反码 补码 都是0
-
java没有无符号数,换言之,java中的数都是有符号的
-
在计算机运行的时候,都是以补码的方式来运算的
-
当我们要看运算结果的时候,要看它的原码
例题: ~2 求2的异或
1.写出2的原码 00000000 00000000 00000000 00000010
2.因为计算机运算的是补码,并且正数的原码 、反码 、补码三者是一样的
3.因此2的补码是 00000000 00000000 00000000 00000010
4.对2的补码进行异或,即11111111 11111111 11111111 11111101
5.最后得到的结果我们要看原码 因为是负数,我们先将补码-1变成反码
6.反码是 11111111 11111111 11111111 11111100
7.负数的原码是 符号位不变其他位取反
7.原码 10000000 00000000 00000000 00000011 得到的结果就是-3
3、final的作用
final关键字可以修饰:
(1)类。类不能被继承。
(2)方法。方法不能被重写,但是可以重载。
(3)基本类型变量。只能被赋值一次,即常量。
(4)引用。只有一次指向对象的机会。
注意final修饰的类是不可变的类 是错误的
类可不可变和类用没有用final修饰是没有直接关系的,而是要看它的底层源码。
常见的不可变类如String它是用final修饰的char数组来存储的源代码:
/** The value is used for character storage. */
private final char value[];
包装类型如Integer的源码:
private final int value;
public Integer(int value) {
this.value = value;
}
而StringBuffer和StringBuilde是用final修饰的但是它们就不属于不可变类源代码:
/**
\* The value is used for character storage.
*/
char[] value;
4、访问修饰符
java提供了四种访问修饰符号,用于控制方法和属性(成员变量)的访问权限(范围)
-
公共级别:用public修饰,对外公开
-
受保护界别:用protected修饰,对子类和同一个包中的类公开
-
默认级别:没有修饰符(或者叫缺省) ,向同一个包的类公开
-
私有级别:用private修饰,只有类本身可以访问,不对外公开
访问级别 | 访问修饰符 | 本类 | 同包 | 子类 | 不同包 |
---|---|---|---|---|---|
公开 | public | √ | √ | √ | √ |
受保护 | protected | √ | √ | √ | × |
缺省(默认) | 没有修饰符 | √ | √ | × | × |
私有 | private | √ | × | × | × |
5、面向对象的三大特征
封装
1、概念
把抽象出来的数据(属性)和对象数据的操作(方法)封装在一起,数据被保护在内部。程序其他部分只能通过被授权的操作(方法),才能对数据进行操作
2、好处
-
隐藏实现细节
-
对数据进行验证,保证安全合理
继承
1、概念
主要解决代码复用性,使用extends关键字
注意:
-
子类自动拥有父类定义的属性和方法
-
父类有叫超类 基类
-
子类有叫派生类
2、好处
-
代码的复用性提高了
-
代码的扩展性和维护性提高了
3、细节
-
子类继承了父类的所有属性和方法(包括私有的),但是私有属性不能在子类中直接访问,要通过父类提供的公共方法才能去访问
-
子类必须调用父类的构造器,完成父类的初始化
-
当创建子类对象的时候,不管子类使用那个构造器,默认情况下总会去调用父类的无参构造,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的那个构造器完成对父类的初始化工作,否则编译不通过。
-
如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)
-
super在使用的时候,只能放在构造器的第一行
-
super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在同一个构造器中
-
java的所有类都是Object的子类 即Object是所有类的基类
-
父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)
-
子类中最大只能继承一个父类(直接继承)。java是单继承机制
-
不能滥用继承,子类父类之间必须满足is - a的逻辑关系
-
例如: 柯基(子类)是一个狗(父类) 挪威那犬(子类)是一个狗(父类)
-
4、继承的本质
多态
1、概念
方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在分封装和继承基础之上的。
主要是提高代码的复用性,便于维护
举例
主人给自己动物喂食的例子 ---动物 ---狗 ---猫 ---食物 ---骨头 ---鱼肉 主人实现一个方法 给动物喂食物 发现 给狗喂骨头 要写一个方法 给猫喂鱼肉 也要写一个方法 如果后期还有的话 我们都要写一个方法 但是我们发现这个方法根本就是 给某个动物 喂某种食物 逻辑是相同的 但是我们确要写很多的方法,并且这些方法是大致相同的 因此引出了多态,用于提高代码的复用性,便于后期的维护
-
方法的重写和重载
-
对象的多态(核心)
一个对象的编译类型和运行类型可以不一致
编译类型在定义对象的时候,就确定了,不能改变、
运行类型是可以变化的
编译类型看定义时候等号的左面 运行类型看等号的右边
2、细节
-
多态的前提: 两个类是继承关系的
-
多态的向上转型:
-
本质:父类的引用指向子类的对象
-
语法:父类类型 引用名 = new 子类类型();
-
特点:编译的时候是父类类型 运行的时候是子类类型
-
可以调用父类所有成员(仍然遵循访问权限)、不能调用子类特有的成员
(编译期间,能调用那些成员,有编译类型绝对)
-
最终运行效果看子类(运行类型决定)的具体实现
-
-
例:(对于重写的方法,最终调用的子类重写的方法)
-
多态的向下转型
-
语法:子类类型 引用名 = (子类类型)父类引用;
-
只能强制父类引用,不能强转父类的对象
(即堆中的父类对象不改变,只是改变了栈中的父类引用)
-
要求父类的引用必须指向的是当前目标类型的对象
例: Animal animal =new Cat() Cat cat =(Cat)animal;
(即其实输出的是动物类,但是你知道它是猫类,这个时候你可以直接强转成猫类)
-
当向下转型后可以就可以调用子类中的所有代码
-
-
属性没有重写一说 属性名看编译类型
属性跟方法是不同的,这点一定要注意
package com.sofwin.controller;
/**
* @packageName: com.sofwin.controller
* @author: wentao
* @date: 2022/10/20 14:28
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class Test0002 {
public static void main(String[]args){
A a=new B();
输出的10 属性没有重写一说,我们看的是编译类型 这一点跟方法是不一样的要记住
System.out.println(a.num);
B b=new B();
//输出20 看编译类型
System.out.println(b.num);
}
}
class A {
int num=10;
}
class B extends A {
int num=20;
}
-
instanceOf 比较操作符
用于判断对象的运行类型是否为XX类型或XX类型的子类型
-
java的动态绑定机制
-
当调用对象方法的时候,该方法会和该对象内存地址/运行类型绑定
-
当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
-