文章目录
算术运算符:自增自减运算符
a是操作数,++是自增运算符;- -是自减运算符,自增和自减运算符即可以放在变量的前面,也可以放在变量的后面,例如:a++、++a、a - -、- -a等。
自增(++)/自减:将变量的值加1
分前缀式(如++a)和后缀式(如a++)。
前缀式是先加1再使用;后缀式是先使用再加1。
辩析:a=a++
a = a++与a = ++a均为先计算后赋值,不同的是:
- a = a++中变量先压栈,后计算,最后栈顶元素弹出赋值于a;
- a = ++a中变量先计算,后压栈,最后栈顶元素弹出赋值于a.
- 详细图解
内存的划分:
- 寄存器。
- 本地方法区。
- 方法区。
- 栈内存。
存储的都是局部变量。
而且变量所属的作用域一旦结束,该变量就自动释放。 - 堆内存。
存储是数组和对象(其实数组就是对象) 凡是new建立在堆中。
特点:
1,每一个实体都有首地址值。
2,堆内存中的每一个变量都有默认初始化值,根据类型的不同而不同。整数是0,小数0.0或者0.0f,boolean false char ‘\u0000’
3,垃圾回收机制。
逻辑运算符
-
逻辑运算符连接两个关系表达式或布尔变量,用于解决多个关系表达式的组合判断问题
-
注意逻辑运算符返回的运算结果为布尔类型。通常,我们用0表示false,用1表示true
-
与:表示并且的关系
- &单与【也叫逻辑与】: &运算的两边只要有一个是false,结果肯定是false;只有两边都为true,结果才是true
- &&双与【也叫短路与】:1 && 2 ,当1是false时,2会被短路,提高程序的效率
- &与&&区别:
&:无论左边的运算结果是什么,右边都参与运算。
& & :当左边为false时,右边不参与运算的。
-
或:表示或者的关系
- |单或【也叫逻辑或】: 1 | 2,结果想要是true,要求1和2只要有一个为true就可以
- ||双或【也叫短路或】:1 || 2,当1是true时,2会被短路,提高程序效率
- |与||区别:
|:无论左边的运算结果是什么,右边都参与运算。
|| :当左边为true时,右边不参与运算的。
-
位运算
- 左移几位其实就是该数据乘以2的几次方。
- <<:可以完成2的次幂运算
- 右移几位,其实就是该数据除以2的几次幂。
- >>:对于高位出现的空位,原来高位是什么就用什么补这个空位。
- 无符号右移>>>:数据进行右移时,高位出现的空位,无论原高位是什么,空位都用0补。
- 左移几位其实就是该数据乘以2的几次方。
变量
-
概念:可以改变的数,称为变量。在Java语言中,所有的变量在使用前必须声明。
-
一般通过“变量类型 变量名 = 变量值 ;”这三部分来描述一个变量。如:int a = 3 ;
-
变量的使用原则:就近原则,即尽量控制变量的使用范围到最小
-
Java中有成员变量、局部变量,没有全局变量。
-
局部变量
位置:定义在方法里或者局部代码块中
注意:必须手动初始化来分配内存.如:int i = 5;或者int i; i = 5;
作用域:也就是方法里或者局部代码块中,方法运行完内存就释放了 -
成员变量
位置:定义在类里方法外
注意:不用初始化,也会自动被初始化成默认值
作用域:整个类中,类消失了,变量才会释放 -
全局变量是全局可见的,Java不支持全局可见的变量,因为:全局变量破坏了引用透明性原则。全局变量导致了命名空间的冲突。
方法(也称函数)
1、方法的重载
方法的重载是指在一个类中定义多个同名的方法,但是每个方法的参数列表不同(也就是指参数的个数和类型不同),程序在调用方法时,可以通过传递给他们的不同个数和类型的参数来决定具体调用哪个方法.
2、方法重写Override
- 继承以后,子类就拥有了父类的功能
- 在子类中,可以添加子类特有的功能,也可以修改父类的原有功能
- 子类中方法的签名与父类完全一样时,会发生覆盖/复写的现象
- 注意: 父类的私有方法不能被重写
- 重写的要求:两同两小一大
两同:方法名 参数列表 要完全一致
两小:
子类返回值类型小于等于父类的返回值类型(注意此处说的是继承关系,不是值大小)
子类抛出异常小于等于父类方法抛出异常
一大:子类方法的修饰符权限要大于等于父类被重写方法的修饰符权限
3、重载(Overload) 和重写(Override) 的区别。重载的方法能否根据返回类型进行区分?
----方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
重写遵循(OCP原则:面向修改关闭,面向拓展开放)
break与continue 的区别
break: 直接结束当前循环,跳出循环体,简单粗暴
break以后的循环体中的语句不会继续执行,循环体外的会执行
注意如果是嵌套for循环,在内层循环遇到了break,只会跳出当前这一层内循环哦
continue: 跳出本轮循环,继续下一轮循环
continue后本轮循环体中的语句不会继续执行,但是会继续执行下轮循环,循环体外的也会执行
数组
- 概念 :同一种类型数据的集合。其实数组就是一个容器。
- 数组的创建方式一般分为动态初始化和静态初始化
动态初始化
int[] a = new int[5];
静态初始化
int[] b = new int[]{1,2,3,4,5};
int[] c = {1,2,3,4,5};
- 数组工具类Arrays
1、Arrays.toString(数组)
把数组里的数据,用逗号连接成一个字符串[值1,值2]
2、Arrays.sort(数组)
对数组进行排序,对于基本类型的数组使用的是优化后的快速排序算法,效率高
对引用类型数组,使用的是优化后的合并排序算法
类与对象
1、对象在内存中的存储
-
Java把内存分成5大区域,我们重点关注栈和堆。
一般来讲局部变量存在栈中,方法执行完毕内存就被释放
对象(new出来的东西)存在堆中,对象不再被使用时,内存才会被释放
每个堆内存的元素都有地址值 对象中的属性都是有默认值的
TIPS: 栈与队列指的是一种数据的结构。
栈:先进后出(FILO – FirstIn Last Out)
队列:先进先出(FIFO – First In First Out)
2、对象的创建过程
- 创建单个对象:
- 创建多个对象:
p2.brand = “HUAWEI”;
就是先到栈内存中找到p2中保存的唯一的地址值
然后根据地址值找到对应的Phone对象,并对其对应的属性值进行修改
p2.eat();
也是先到栈内存中找到p2中保存的唯一的地址值
然后根据地址值找到对应Phone对象,执行Phone对象的eat()方法
OOP
oop指的是面向对象的三大特性:封装、继承、多态
1. 封装(Encapsulation):
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
private:私有,是一个权限修饰符。用于修饰成员。
私有的内容只在本类中有效。
注意:私有仅仅是封装的一种体现而已。
访问控制符
用来控制一个类,或者类中的成员的访问范围。
TIPS:default是表示不写修饰符,默认,如果写default单词来修饰会报错
2. 继承:
- 继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并扩展新的能力.
Java继承是会用已存在的类的定义作为基础建立新类的技术
新类的定义可以增加新的数据或者新的功能,也可以使用父类的功能,但不能选择性的继承父类(超类/基类) - 特点
- 使用extends关键字来表示继承关系
- 相当于子类把父类的功能复制了一份
- Java只支持单继承
- 继承可以传递(爷爷/儿子/孙子这样的关系)
- 父类的私有成员也会被继承,但由于是私有的不可见,所以子类不能使用父类的私有资源
- 继承多用于功能的修改,子类可以在拥有父类功能的同时,进行功能拓展
- 是is a的关系
继承中变量的使用
当父类与子类的成员变量同名的时候,可以使用super指定父类的成员变量
我们可以把super看做是父类的对象
继承中构造方法的使用
1.子类在创建对象时,默认会先调用父类的构造方法
2.原因是子类的构造函数中第一行默认存在super()--表示调用父类的无参构造
3.当父类没有无参构造时,可以通过super(参数)调用父类的其他含参构造
但不可以不调用任何一个父类的构造函数,必须选一个来调用
4.构造方法不可以被继承!因为语法的原因:构造方法名是类名,子类里不能写一个父类名字的构造方法
继承中方法的使用
子类对象可以调用继承自父类的方法
子类对象调用自己独有的方法
3、多态
1.概念
多态是面向对象程序设计(OOP)的一个重要特征,指同一个实体同时具有多种形式,即同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。
比如,你的女盆友让你买点水果回来,不管买回来的是苹果还是西瓜,只要是水果就行,这个就是生活中多态的体现
再比如,小猫、小狗、小猪我们可以把他们都归纳成小动物,每种小动物都需要吃东西,所以我们可以统一设置他们都必须吃,但是每种小动物的习性不一样,那这个就可以设置成小动物自己特有的功能,多态对象只能调用父类中定义子类中重写的功能,并不能调用子类的特有功能,这样就实现了代码的统一
2. 特点
- 多态的前提1:是继承
- 多态的前提2:要有方法的重写
- 父类引用指向子类对象,如:Animal a = new Cat();
解释:创建出来的子类对象的地址值交给父类类型的引用类型变量来保存 - 多态中,编译看左边,运行看右边
必须要父类定义这个方法,才能通过编译,编译时,把多态对象看作是父类类型
必须要子类重写这个方法,才能满足多态,运行时实际干活的是子类
3.多态的使用
-
前提:多态对象把自己看做是父类类型
-
成员变量: 使用的是父类的
-
成员方法: 由于存在重写现象,所以使用的是子类的
方法的声明的使用的是父类的,方法的实现使用的是子类的 -
静态成员: 随着类的加载而加载,谁调用就返回谁的
如果父子类都有同名的静态方法,使用的是父类的
因为多态对象把自己看作是父类型,直接使用父类的静态资源
构造方法
1、 构造方法
1、概念
- 构造方法是一种特殊的方法,它是一个与类同名且没有返回值类型的方法
构造方法的主要功能就是完成对象创建或者初始化
当类创建对象(实例化)时,就会自动调用构造方法
构造方法与普通方法一样也可以重载. - 特点:方法名与类名相同,且没有返回值类型
执行时机:创建对象时立即执行
默认会创建无参构造,但是,如果自定义了含参构造,默认的无参构造会被覆盖,注意要手动添加哦
2、 构造代码块与局部代码块
形式:
{ 代码… }
1、构造代码块
- 位置: 在类的内部,在方法的外部
- 作用: 用于抽取构造方法中的共性代码
- 执行时机: 每次调用构造方法前都会调用构造代码块
- 注意事项:构造代码块优先于构造方法加载
2、局部代码块
- 位置: 在方法里面的代码块
- 作用: 通常用于控制变量的作用范围,出了花括号就失效
- 注意事项: 变量的作用范围越小越好,成员变量会存在线程安全的问题
3、执行顺序
构造代码块>构造方法>对象创建成功>普通方法>局部代码块
- 1.当创建对象时,会触发构造函数
- 2.创建对象时,也会触发构造代码块,而且构造代码块优先于构造方法执行的
- 3.我们通过创建好的对象来调用普通的方法
- 4.如果调用的普通方法里有局部代码块,对应的局部代码块才会执行
4、this关键字与super关键字
this
- 概念:this代表本类对象的一个引用对象
- 使用:通过this关键字来调用成员变量 ,前提:成员变量与局部变量同名时;this还可以在构造方法间相互调用,this关键字必须在构造方法中的第一行。
super
- 可以通过这个关键字使用父类的内容,Super代表的是父类的一个引用对象
- 注意:在构造方法里,出现的调用位置必须是第一行
- 当父类与子类的成员变量同名的时候,可以使用super指定父类的成员变量
this与super的区别
this代表的是本类对象的引用,我们可以把this看作是Cat this = new Cat();
super代表的是父类对象的引用,我们可以把super看作是Father super = new Father();
当本类的成员变量与局部变量同名时,需要使用this.变量名指定本类的成员变量
当本类的成员变量与父类的成员变量同名时,需要使用super.变量名指定父类的成员变量
this可以实现调用本类构造方法的功能,不能互相调用,需要写在构造方法首行
this();表示调用本类的无参构造 this(参数);表示调用本类的对应参数的构造
super也可以实现调用父类构造方法的功能
super();表示调用父类的无参构造 super(参数);表示调用父类的对应参数的构造
注意:super的使用前提是继承,没有父子类关系,就没有super
注意:this调用构造方法或者super调用构造方法,都必须出现在构造方法的第一行
注意:如果父类没有无参构造,需要手动在子类构造方法的第一行调用其他的含参构造
拓展:如果子类重写了父类的方法以后,可以使用super.方法名(参数列表)来调用
3、 创建对象的流程
Person p = new Person();//短短这行代码发生了很多事情
- 把Person.class文件加载进内存
- 在栈内存中,开辟空间,存放引用变量p
- 在堆内存中,开辟空间,存放Person对象
- 对成员变量进行默认的初始化
- 对成员变量进行显示初始化
- 执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
- 堆内存完成
- 把堆内存的地址值赋值给变量p ,p就是一个引用变量,引用了Person对象的地址值