位运算&面向对象
1 位运算
1.1 进制
二进制: 0-1 满2进1 用0b来表示 0b0011
八进制: 0-7 满8进1 用0开头来表示 015
十进制: 0-9 满10进1 11
十六进制:0-9 a-f 满十六进一 用0x开头来表示 0xabc a-f不区分大小写
进制的相互转换:
十进制转换成二进制:不断除以2取余,然后将余数倒排。
二进制转换成十进制:从低位起,按位次乘以2的位次幂,然后求和。
1101 = 1 * 2 ^0 + 0 * 2 ^ 1 + 1 * 2 ^ 2 + 1 * 2 ^ 3 = 1 + 4 + 8 = 13
十进制向哪个进制转换就除以哪个进制,然后取余倒排。
二进制向八进制转换:从低位次起,每三位当作一组,产生一位八进制数字,最高位不足三位,补0.三位以内,按照二进制向十进制的转换规则进行运算,产生的八进制数字按照顺序排列
八进制转二进制:一变三的过程。每一位八进制都转换成三位的二进制,然后将这些数字排列
二进制转十六进制:四变一的过程 和二进制转八进制相同,只是把每四位当作一组。
1111 0101 = 0xf5
十六进制转二进制:一变四的过程。
1.2 原码反码补码
所有的数据在底层都是二进制数据的补码形式存储的。
正数的原码反码和补码是一样的。
练习:
10110101 原码 --> 11001011 补码
10110101 补码 --> 11001011 原码
1.3 位运算
位运算要把数据转成二进制的补码形式进行计算。位运算相对于其他运算符,执行效率更高。
& 按位与 两个操作数都是1,结果才是1,否则结果就是0
任意一个数&一个偶数,结果一定是偶数
任意一个数&1,如果结果是0,就是一个偶数
| 按位或 两个位只要有一个是1,那么结果就是1,否则就是0
任意一个数|一个奇数,结果一定是奇数
任意一个数|0,结果还是自身
^ 按位异或 两个位相同结果是0,不同结果是1
任意一个数异或自己都是0,异或0就是自身
<< 左移 左移n位,左边舍弃,右边补0.对于正整数来说,左移n位就是乘以2的n次方。
3 << 2 = 12
0000 0011
00 001100 = 12
>> 右移 右移n位就是右边舍弃,左边补位(正数补0,负数补1) 对于正整数来说,右移n位就是除以2的n次方
5 >> 2 = 1
0000 0101
00 0000 01 = 1
>>> 无符号右移 和右移类似,但是最高位空出之后,无论正数还是负数,一律补0。
~ 取反 将数字转换成二进制之后,1变0,0变1,然后最高位按照其数值计算(比如八位,最高位如果是1,就是-128),其余位按照二进制转十进制的规则进行计算,然后加上最高位(-128)
结论: ~i = -i - 1;
~3
0000 0011
1111 1100 -128 + 64 + 32 + 16 + 8 + 4 = -4
练习: -5 >> 2
-5
原码 10000000 00000000 00000000 00000101
反码 11111111 11111111 11111111 11111010
补码 11111111 11111111 11111111 11111011
右移后的补码: 1111111111 11111111 11111111 111110
反码:1111111111 11111111 11111111 111101
原码:1000000000 00000000 00000000 000010
补充: 两个值交换变量
public static void main(String[] args) {
int a = 10;
int b = 20;
// 交换a b的值
// 定义第三个变量
// int temp = a;
// a = b;
// b = temp;
// System.out.println(a);
// System.out.println(b);
// 第二种方案
// a = b - a;
// b = b - a;//b = b - (b - a) = b - b + a = a
// a = b + a;//a = a + (b - a) = b
// System.out.println(a);
// System.out.println(b);
// 第三种方案
a = a ^ b;
b = a ^ b; // b = a ^ b ^ b = a
a = a ^ b; // a = a ^ b ^ a = b
System.out.println(a);
System.out.println(b);
}
2 二维数组[了解]
二维数组中的每一个元素都是一个一维数组
二维数组的定义格式:
数据类型[][] 数组名称 推荐
数据类型 数组名称[][] 了解
数据类型[] 数组名称[] 奇葩
二维数组的初始化:
- 动态初始化(指定长度)
- 数据类型[][] 数组名称 = new 数据类型[m][n];
- m:代表二维数组中一维数组的个数
- n:一维数组中元素的个数
- n可以省略,代表小数组长度不确定
- 静态初始化(指定内容)
- 完整格式:数据类型[][] 数组名称 = new 数据类型[][]{{元素1,元素2},{元素3,元素4,元素5},{元素6}};
- 简便格式: 数据类型[][] 数组名称 ={{元素1,元素2},{元素3,元素4,元素5},{元素6}};
public static void main(String[] args) {
// 定义二维数组 {{0,0},{0,0},{0,0}}
// 动态初始化
int[][] array = new int[3][2];
System.out.println(array);// [[I@5594a1b5
System.out.println(array[0]);// [I@6a5fc7f7
System.out.println(array[2]);
System.out.println(array[1][0]);
// 静态初始化
// int[][] arr1 = new int[][]{{1,2,3},{4,5,6,7},{8,9}};
int[][] arr1 = {{1,2,3},{4,5,6,7},{8,9}};
System.out.println(arr1[1][3]);
// 遍历二维数组
for (int i = 0; i < arr1.length; i++) {
int[] tempArr = arr1[i];
for (int j = 0; j < tempArr.length; j++) {
System.out.println(tempArr[j]);
}
}
}
3 面向对象
3.1 面向对象思想概述
面向对象思想是相对于面向过程而言的。
面向过程强调的是每一个功能的步骤,面向对象思想强调的是对象,由对象去调用对应的功能。
特点:
- 是一种更符合我们思考习惯的思想
- 可以将复杂的事情简单化
- 我们从执行者变成了指挥者
面向过程的代表语言就是C语言,面向对象的代表语言就是java语言
3.2 类与对象及其使用
我们学习编程语言,就是为了模拟现实世界的事物。比如银行系统,健身房系统,会员系统,办公系统…
我们如何表示一个现实世界的事物?
- 属性
- 就是该事物描述的信息
- 行为
- 就是该事物能够做什么
java语言的最基本单位是类,所有的事物都用类来体现。
类:是一组相关的属性和行为的集合。
java中的类(class)描述事物
- 成员变量(属性) 描述事物的信息
- 成员方法(行为) 描述事物能够做什么
对象:就是类的一个具体体现。
定义类其实就是定义成员变量和成员方法
- 定义成员变量和以前定义变量的是一样的,只是位置发生了改变,在类中方法外定义,就是成员变量。
- 定义成员方法和以前定义方法一样,只不过需要把static这个关键字去掉。
public class Student {
// 成员变量(属性)
// 姓名
String name;
// 年龄
int age;
// 成员方法
public void study(){
System.out.println("好好学习天天向上!");
}
}
对象的创建和使用
格式: 类名 对象名 = new 类名();
使用对象访问类中的成员:
- 对象名.成员变量
- 对象名.成员方法
public static void main(String[] args) {
// 创建对象
Student student = new Student();
// 打印对象实际就是打印的地址值
System.out.println(student);
System.out.println(student.name);//null
System.out.println(student.age);// 0
student.age = 18;
student.name = "刘诗诗";
// 调用成员变量
System.out.println(student.name);// 刘诗诗
System.out.println(student.age);// 18
// 调用成员方法
student.study();
}
3.3 对象的内存图
定义Phone
public class Phone {
// 成员变量
// 品牌
String brand;
// 价格
int price;
// 颜色
String color;
// 成员方法
public void call(String name){
System.out.println("给" + name + "打电话");
}
public void sendMessage(){
System.out.println("大哥大嫂新年好~");
}
}
测试代码
public static void main(String[] args) {
// 创建对象 类名 对象名 = new 类名();
Phone phone = new Phone();
System.out.println(phone);// 6a5fc7f7
System.out.println(phone.brand);// null
System.out.println(phone.price);// 0
System.out.println(phone.color);// null
// 调用成员变量
phone.brand = "华为";
phone.color = "中国红";
phone.price = 6999;
System.out.println(phone.brand);
System.out.println(phone.color);
System.out.println(phone.price);
// 调用成员方法
phone.call("赵丽颖");
phone.sendMessage();
}
两个对象引用一个地址
public static void main(String[] args) {
// 创建对象
Phone phone = new Phone();
System.out.println(phone);// 6a5fc7f7
System.out.println(phone.price);// 0
System.out.println(phone.color);// null
System.out.println(phone.brand);// null
Phone phone1 = phone;
phone.brand = "oppo";
phone.price = 2999;
phone.color = "乳白色";
phone1.brand = "小米";
phone1.price = 3999;
phone1.color = "冷风蓝";
System.out.println(phone.brand); // 小米
System.out.println(phone.price); // 3999
System.out.println(phone.color); // 冷风蓝
System.out.println(phone1.brand); // 小米
System.out.println(phone1.price); // 3999
System.out.println(phone1.color); // 冷风蓝
System.out.println(phone1);
}
3.4 成员变量和局部变量的区别
- 在类中的位置不同
- 成员变量:类中,方法外
- 局部变量:方法中或者方法的声明上(形式参数)
- 生命周期不同:
- 成员变量:随着对象的创建而存在,随着对象的销毁而销毁
- 局部变量:方法调用后到定义那一行出现,随着方法调用完毕而销毁
- 内存位置不同:
- 成员变量:在堆中
- 局部变量:在栈中
- 初始化值不同
- 成员变量有默认值.
- 局部变量没有默认值,必须先定义再赋值
3.5 封装
面向对象的三大特征:封装、继承、多态
private是一个关键字,是一个权限修饰符,来修饰成员变量和成员方法
被private修饰的成员只能在本类中可以访问,其他地方都不能访问。
private最常见的应用:
- 把成员变量用private进行修饰
- 提供setXxx()和getXxx方法
- 好处:
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 通过方法封装了代码,提高了代码的复用性
3.6 this关键字
this代表所在类的对象的引用。方法被哪个对象调用,this就是哪个对象
this的用法
this.成员变量 获取当前对象的成员变量
this.成员方法 调用当前对象的成员方法
this() 调用当前对象的构造方法
注意点:this()必须在有效代码的第一行
3.7 构造方法
-
作用:给对象的数据进行初始化
-
格式
- 方法名和类名相同
- 没有返回值类型,没有void
- 没有具体的返回值
修饰符 类名(参数列表){ }
-
构造方法是可以重载的
-
如果没有提供任何构造方法,系统会给出一个默认的无参构造方法
-
如果提供了构造方法,系统将不再提供默认的无参构造方法
public class Student {
// 成员变量(属性)
// 姓名
private String name;
// 年龄
private int age;
public Student(){}
public Student(int age){
this.age = age;
}
public Student(String name){
this.name = name;
}
public Student(String name,int age){
this.name = name;
this.age = age;
}
// 给成员变量赋值 setXxx
public void setAge(int age){
System.out.println(this);
// java有就近原则
this.age = age;
}
public void setName(String name){
this.name = name;
}
// 获取成员变量 getXxx
public int getAge(){
return age;
}
public String getName(){
return name;
}
// 成员方法
public void study(){
System.out.println("好好学习天天向上!" + age);
this.sleep();
}
public void sleep(){
System.out.println("劳逸结合~");
}
}
3.8 构造代码块
package cn.javasm.demo;
/**
* @author gfs
* @version 0.1
* @className Baby
* @date 2023/12/18 17:07
* @description 定义一个婴儿类
* @since jdk11
*/
public class Baby {
// 姓名
private String name;
// 体重
private double weight;
// 构造代码块 在每一次创建对象时都会执行 而且是先于构造方法执行的
{
System.out.println("构造代码块执行了");
this.cry();
this.eat();
}
// 构造方法
public Baby(){
}
public Baby(String name){
System.out.println("构造方法执行了");
this.name = name;
}
public Baby(double weight){
this.weight = weight;
}
public Baby(String name,double weight){
this.name = name;
this.weight = weight;
}
public void setName(String name){
this.name = name;
}
public void setWeight(double weight){
this.weight = weight;
}
public String getName(){
return name;
}
public double getWeight(){
return weight;
}
// 成员方法
public void cry(){
System.out.println("婴儿哇哇大哭");
}
public void eat(){
System.out.println("婴儿都要吃奶");
}
}
补充:局部代码块
// 局部代码块 提高内存的利用率 限制变量的作用范围和生命周期
{
int i = 10;
System.out.println(i);
}
练习: 定义一个类表示矩形,提供求其周长和面积的方法。
public class TestDemo {
public static void main(String[] args) {
// 创建矩形对象
Rectangle rectangle = new Rectangle(3.0,4.0);
System.out.println(rectangle.getGirth());
System.out.println(rectangle.getArea());
System.out.println(rectangle.getWidth());
}
}
// 代表矩形的类
class Rectangle{
private double width;// 宽
private double length;// 长
// 提供构造方法来给长和宽赋值
public Rectangle(double width,double length){
if (width > 0 && length > 0){//长和宽不可能是负数或者0
this.width = width;
this.length = length;
}
}
/**
* 求周长的方法
* @return 周长
*/
public double getGirth(){
return 2 * (length + width);
}
/**
* 求面积的方法
* @return 面积
*/
public double getArea(){
return length * width;
}
public double getWidth(){
return width;
}
// 矩形出现之后就有了长和宽 并且不能修改
// public void setWidth(double width){
// this.width = width;
// }
public double getLength(){
return length;
}
// public void setLength(double length){
// this.length = length;
// }
}
th;
this.length = length;
}
}
/**
* 求周长的方法
* @return 周长
*/
public double getGirth(){
return 2 * (length + width);
}
/**
* 求面积的方法
* @return 面积
*/
public double getArea(){
return length * width;
}
public double getWidth(){
return width;
}
// 矩形出现之后就有了长和宽 并且不能修改
// public void setWidth(double width){
// this.width = width;
// }
public double getLength(){
return length;
}
// public void setLength(double length){
// this.length = length;
// }
}