目录
%取模的本质是: 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
二进制的最高为是符号位: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
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;
java提供了四种访问修饰符号,用于控制方法和属性(成员变量)的访问权限(范围)
公共级别:用public修饰,对外公开
受保护界别:用protected修饰,对子类和同一个包中的类公开
默认级别:没有修饰符(或者叫缺省) ,向同一个包的类公开
私有级别:用private修饰,只有类本身可以访问,不对外公开
| 访问级别 | 访问修饰符 | 本类 | 同包 | 子类 | 不同包 |
|---|---|---|---|---|---|
| 公开 | public | √ | √ | √ | √ |
| 受保护 | protected | √ | √ | √ | × |
| 缺省(默认) | 没有修饰符 | √ | √ | × | × |
| 私有 | private | √ | × | × | × |
把抽象出来的数据(属性)和对象数据的操作(方法)封装在一起,数据被保护在内部。程序其他部分只能通过被授权的操作(方法),才能对数据进行操作
隐藏实现细节
对数据进行验证,保证安全合理
主要解决代码复用性,使用extends关键字
注意:
子类自动拥有父类定义的属性和方法
父类有叫超类 基类
子类有叫派生类
代码的复用性提高了
代码的扩展性和维护性提高了
子类继承了父类的所有属性和方法(包括私有的),但是私有属性不能在子类中直接访问,要通过父类提供的公共方法才能去访问
子类必须调用父类的构造器,完成父类的初始化
当创建子类对象的时候,不管子类使用那个构造器,默认情况下总会去调用父类的无参构造,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的那个构造器完成对父类的初始化工作,否则编译不通过。
如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)
super在使用的时候,只能放在构造器的第一行
super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在同一个构造器中
java的所有类都是Object的子类 即Object是所有类的基类
父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)
子类中最大只能继承一个父类(直接继承)。java是单继承机制
不能滥用继承,子类父类之间必须满足is - a的逻辑关系
例如: 柯基(子类)是一个狗(父类) 挪威那犬(子类)是一个狗(父类)

方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在分封装和继承基础之上的。
主要是提高代码的复用性,便于维护
举例
主人给自己动物喂食的例子 ---动物 ---狗 ---猫 ---食物 ---骨头 ---鱼肉 主人实现一个方法 给动物喂食物 发现 给狗喂骨头 要写一个方法 给猫喂鱼肉 也要写一个方法 如果后期还有的话 我们都要写一个方法 但是我们发现这个方法根本就是 给某个动物 喂某种食物 逻辑是相同的 但是我们确要写很多的方法,并且这些方法是大致相同的 因此引出了多态,用于提高代码的复用性,便于后期的维护
方法的重写和重载
对象的多态(核心)
一个对象的编译类型和运行类型可以不一致
编译类型在定义对象的时候,就确定了,不能改变、
运行类型是可以变化的
编译类型看定义时候等号的左面 运行类型看等号的右边
多态的前提: 两个类是继承关系的
多态的向上转型:
本质:父类的引用指向子类的对象
语法:父类类型 引用名 = 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的动态绑定机制
当调用对象方法的时候,该方法会和该对象内存地址/运行类型绑定
当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用