运算符
一 . 算数运算符
+加法运算 ,字符串连接运算
-减法运算
*乘法运算
/除法运算
%取模运算 , 两个数字相除取余数
++ , --自增自减运算
1.独立运算
前++和 后++没有区别 例如 ++i i++
2.混合运算
和其他变量放在一起 , 前++和 后++就产生了不同
int a = 1;
int b =++a; // b=2 , a=2
int b=a++; // b=1 , a=2
总结就是 : 只要有自增运算符, 那么自己肯定是增长的 , 就看是先赋值 , 还是后赋值了
3.任何数据类型和字符串进行拼接的时候 , 结果都会变成字符串
System.out.println("5+5="+5+5); //输出5+5=55
二 . 赋值运算符
=等于号
+=加等于
-=减等于
*=乘等于
/=除等于
%=取模等
赋值运算符 , 就是将符号左边的值 , 赋值给左边的变量
int i=5;
i+=5
System.out.println(i);//i=10
计算方式 i=i+5 变量i先加5 ,再赋值变量i
三 . 比较运算符
==比较符号两边数据是否相等 ,相等结果是true
<比较符号左边的数据是否小于右边的数据 , 如果小于结果是true
>比较符号左边的数据是否大于右边的数据 ,如果大于结果是true
<=比较符号左边的数据是否小于或者等于右边的数据, 如果大于结果是false
>=比较符号左边的数据是否大于或者等于右边的数据,如果小于结果是false。
!=不等于符号 ,如果符号两边的数据不相等,结果是true。
比较运算符 , 是两个数据之间进行比较的运算 , 运算的结果都是布尔值true 或者false
四 . 逻辑运算符
逻辑运算符包括
&&短路与1.两边都是true,结果是true 2.一边是false ,结果是false 短路与特点 符号左边是false,右边不再运算
||短路或1.两边都是false ,结果是false 2.一边是true , 结果是true 短路特点: 符号左边是true ,右边不再运算
! 取反1. !true结果是false 2. !false结果是true
逻辑运算符 结果都是布尔值 true或者false
五 . 三元运算符
数据类型 变量名 = 布尔类型表达式 ? 结果1:结果2
结果是true 结果1赋值给变量
结果是false 结果2赋值给变量
int i = (1==2 ? 100 : 200);
System.out.println(i);//200
数据类型转换
1.自动转换
long num=100;
左边是long类型 , 右边是默认的int类型 , 左右不一样
int →long 符合了数据范围从小到大的要求, 所以发生了自动类型转换
2.强制类型转换
int num =(int)100L;
格式 : 范围小的类型 范围小的变量名 =(范围小的类型) 原本范围大的数据 ;
强烈注意: 浮点转换成整数 , 直接取消小数点, 可能造成数据损失精度 ;
if else 判断语句
第一种格式
if(关系表达式){
语句体;
}
第二种格式 if...else
if(关系表达式){
语句体1;
}else{
语句体2;
}
第三种格式if...else if ...else
if(判断条件1){
执行语句1;
}else if(判断条件2){
执行语句2;
} else if(判断条件N){
执行语句n;
}else {
执行语句N+1;
}
switch选择语句
switch(表达式){
case 常量值1:
语句体1;
breack;
case 常量值2:
语句体2;
breack;
default:
语句体N+1;
breack;
}
case穿透性
在switch语句中 , 如果case的后面不写break , 将出现穿透现象 , 也就是不会再判断下一个case值 , 直接向后运行 , 直到遇到break ;
for循环语句
for(初始表达式;布尔表达式;步进表达式){
循环体 ;
}
for循环的执行流程
for(初始化表达式1 ; 布尔表达式2; 步进表达式4 ){
循环体3 ;
}
执行流程 : 1234→234→234
也就是满足表达式 , 先执行循环体 ;
while循环语句
while(布尔表达式){
循环体
步进表达式
}
do while 虚幻语句
do{
System.out.println("无条件执行一次");
}while(false);
特点: 无条件执行一次 , 即使我们将循环条件直接写成false , 也依然会循环一次 ;
breack continue 区别
遇到break , 直接跳出去即可 ;
public static void main(String[] args) {
for(int i=1;i<10;i++){
if (i==4){
break;
}
System.out.println("我爱你");
}
}
遇到continue , 立即跳过当前的循环内容 , 马上开始下一次循环
public static void main(String[] args) {
for(int i=1;i<10;i++){
if (i==4){
continue;
}
System.out.println("我爱你"+i);
}
}
//就只是没有4
break 和continue 都是跳出本次循环 , 但是break是往后都不执行 , continue 是继续执行下边的内容
方法
这个方法例如我们初高中做的题目 那么()中的值就是我们已知的条件 , int 就是我们需要得出的结果的类型
并且我们需要return 结果 ;
public int select(long value){
}
成员变量和局部变量的区别
变量写在方法中 局部变量
变量写在类中 成员变量
成员方法的使用
public void eat(){
System.out.println("正在吃饭");
}
成员方法就是不带有static的
成员变量以及成员方法的使用
对象 . 成员变量 成员变量不赋值的话 , 会有一个默认值 null 0
对象.成员方法()
另外不同包下想互相使用对象 , 就要先进行导包
构造方法
这是一个学生类的构造方法
public class Student {
//创建一个构造方法
public Student (){
System.out.println("魔尊自己创建的构造方法");
}
}
创建一个Demo类进行调用构造方法
public class DemoStudent {
public static void main(String[] args) {
//new 一个对象 就是在调用这个类的构造方法
Student student = new Student();
}
}
new 一个对象 , 就是在调用这个类的构造方法
注意事项 :
1.构造方法的名称必须和所在的类名完全一样 , 就连大小写也要一样
2.构造方法不要写返回值类型 , 连void都不写
3.构造方法不能return一个具体的返回值
4.如果没有编写任何构造方法 , 那么编译器将会默认赠送给你一个构造方法 , 没有参数 ,方法体什么事情都不做
5.一旦编写一个构造方法 , 那么编译器将不再赠送
6.构造方法也是可以进行重载的(意思是可以有多个构造方法)
重载就是方法名相同 , 参数列表不同
7.当你new对象的时候 , 带参数调用的就是有参构造方法 , 不带参数 , 调用的就是无参构造方法
This关键字
专门用来解决局部变量和类的成员变量重名的情况 this.变量 就是用的成员变量
public class Person {
String name ="王健林";
public void sayHello(String name){
System.out.println(name+"你好,我是"+this.name);
}
}
public class SayHello {
public static void main(String[] args) {
Person person = new Person();
person.sayHello("王思冲");
}
}
注意事项 :
当方法的局部变量和类的成员变量重名的时候 , 根据"就近原则" , 优先使用局部变量
如果需要访问本类当中的成员变量 , 需要使用格式 : this.成员变量
你就会发现 这个成员变量 和你方法中的this.成员变量 颜色都变成一样的紫色了
局部变量的前边什么都不要写
this.成员变量 = 对象 .成员变量
Private关键字
private关键字 和 get set方法结合使用 只有本类可以随便访问 , 其他类要通过get set 方法间接访问
person类这个方法中可以把年龄修改成任意数值 , 显然是不对的
然后我们把年龄修改成private
一旦使用了private进行修饰 , 那么本类当中仍然可以随意访问
但是 ! 超出了本类范围之外就不能再直接访问了
那么就间接访问
间接访问private成员变量 , 就是定义一对Getter/Setter方法
必须叫setXXX 或者是getXXX命名规则
对于Getter来说 , 不能有参数, 返回值类型和成员变量对应
对于Setter来说 , 不能有返回值 , 参数类型和成员变量对应
static关键字
一旦使用了static关键字 , 那么这样的内容不再属于对象自己 , 而是属于类 , 所以凡是本类的对象 , 都共享同一份
staitc关键字修饰成员变量
当把成员变量用static修饰的时候 , 这样就new出来的对象都可以共享同一个值 , 当然你不想使用这个共用的值 ,你也可以自己来对他进行赋值
staitc关键字修饰成员方法
public class DemoStudent {
public static void main(String[] args) {
Student student = new Student();
student.method();
student.staticmethod(); //这是通过对象进行调用静态方法 , 正确但是不推荐
Student.staticmethod(); //调用静态方法直接使用类进行调用即可
}
}
另外静态不可以调用非静态
静态代码块
public class 类名称{
static {
//静态代码块的内容
}
}
直接在一个类里面写一个static加一个{}
特点 : 当第一次用到本类时 ,静态代码块执行唯一的一次
静态代码块优先于构造方法执行
静态代码块的典型用途 :
用来一次性的对静态成员变量进行赋值
继承
继承主要解决的问题就是共性抽取 成员方法 成员变量都是可以继承的
在父子类的继承关系中 , 如果成员变量重名 , 则创建子类对象 , 访问有两种方式
直接通过子类对象访问成员变量 :
等号左边是谁 , 就优先使用谁 , 就看你左边创建使用的是什么类
间接通过成员方法访问成员变量 :
该方法属于谁 , 就调用谁的成员变量
1.当子类中成员变量 局部变量 父类中成员变量 都重名的时候 ?
public class FU {
String num="父亲";
}
public class ZI extends FU{
String num="儿子";
public void method(){
String num="孙子";
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num); //父类中用super
}
}
public class Demo {
public static void main(String[] args) {
ZI zi = new ZI();
zi.method();
}
}
2.继承中子类成员方法 和父类成员方法重名 , 会访问谁呢 ?
规则 : 创建的对象是谁 , 就优先用谁 , 如果没有则向上找 就看new的是谁 , 就调用谁 !
重写与重载的区别
重写 : 方法名一样 , 参数列表一样
重载 : 方法名一样 , 参数列表不一样
public class FU {
public void method(){
System.out.println("父类方法执行了");
}
}
public class ZI extends FU{
@Override
public void method1(){
System.out.println("子类方法执行了");
}
}
这个@Override就是用来检测子类是否正确进行了重写 , 如果不对则会报错 , 起到一个检测作用 , 不写也没事,
只需要在子类中进行书写即可
注意事项 :
子类方法的返回值必须[小于等于]父类方法的返回值范围 object类是最高类
子类方法的权限必须[大于等于]父类方法的返回值范围
其实这两点也不用考虑 百分之99都是一样的
Abstract
抽象方法 : 就是加上abstract关键字 , 然后去掉大括号 , 直接分号结束
抽象类 : 抽象方法所在的类 , 必须是抽象类才行 , 在class之前写上abstract即可
public abstract class Animal {
public abstract void eat();
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("吃骨头");
}
}
public class Demo {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
}
}
如何使用抽象类和抽象方法 :
1.不能直接创建new抽象类对象
2.必须用一个子类来继承抽象父类
3.子类必须覆盖重写抽象父类当中所有的抽象方法 子类去掉抽象方法的abstract关键字 , 然后补上方法体大括号
4.创建子类对象进行使用
接口
接口的定义
public interface 接口名称 {
// 抽象方法
// 默认方法
// 静态方法
}
接口中包含的方法
java7 包含 : 1.常量 2. 抽象方法
java8 包含 : 3.默认方法 4.静态方法
java9 包含 : 5.私有方法
接口不可以直接使用 , 必须有一个实现类来实现该接口
接口中的抽象方法的使用
public interface Demointerface {
public abstract void method();
}
注意事项:
1.接口当中的抽象方法 , 修饰符必须是两个固定的关键字 public abstract
2.这两个关键字修饰符 , 可以选择性的省略 .
接口中默认方法的使用
public interface Demointerface {
public abstract void method();
public default void methodA(){
System.out.println("这是一个默认方法");
}
}
这个默认方法 实现类不用进行重写也可以使用
接口中静态方法的使用
public static 返回值类型 方法名称 (参数列表){
方法体
}
通过接口名称 , 直接调用其中的静态方法
接口名称 .静态方法名(参数);
接口中私有方法的使用
我们需要抽取一个共有的方法 , 用来解决两个默认方法之间重复代码的问题 , 但是这个共有方法不应该让实现类使用,应该是私有化的
私有方法刚好可以解决 java9新添加的
1.普通私有方法 : 解决多个默认方法之间重复代码问题
格式 :
private 返回值类型 方法名称 (参数列表) {
方法体
}
2.静态私有方法 , 解决多个静态方法之间重复代码问题
格式
private static 返回值类型 方法名称 (参数列表){
方法体
}
接口中成员变量的使用 :
接口中也可以定义成员变量 , 但是必须使用public static final 三个关键字进行修饰 , 从效果上看 ,其实就是常量
格式
public static final 数据类型 常量名称 =数据值 ;
一旦使用了final 关键字进行修饰 , 说明不可改变
注意事项 :
1.接口中的常量 ,可以省略public static final , 注意 ; 不写也照样是也可以的
2.接口当中的常量 必须进行赋值 , 不能不赋值
3.接口当总常量的名称 ,使用完全大写的字母 ,用下划线进行分割
在Java 9+版本中,接口的内容可以有:
成员变量其实是常量,格式:public [final] 数据类型 常量名称 = 数据值;注意:常量必须进行赋值,而且一旦赋值不能改变。常量名称完全大写,用下划线进行分隔。
接口中最重要的就是抽象方法,格式:public 返回值类型 方法名称(参数列表);注意:实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类。
从Java 8开始,接口里允许定义默认方法,格式:[public] default 返回值类型 方法名称(参数列表) { 方法体 }注意:默认方法也可以被覆盖重写
从Java 8开始,接口里允许定义静态方法,格式:[public] static 返回值类型 方法名称(参数列表) { 方法体 }注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法
从Java 9开始,接口里允许定义私有很乏,格式:普通私有方法:private 返回值类型 方法名称(参数列表) { 方法体 }静态私有方法:private static 返回值类型 方法名称(参数列表) { 方法体 }注意:private的方法只有接口自己才能调用,不能被实现类或别人使用。
继承父类并实现多个接口
1.接口是没有静态代码块或者构造方法的
2.一个类的直接父类是唯一的 , 但是一个类可以同时实现多个接口
3.如果实现类所实现的多个接口当中 , 存在重复的抽象方法 , 那么只需要覆盖重写一次即可
4.如果实现类没有覆盖重写所有接口当中的所有抽象方法 , 那么实现类就必须是一个抽象类
5.如果实现类实现的多个接口当中 , 存在重复的默认方法 , 那么实现类一定要对冲突的默认方法进行覆盖重写
6.一个类如果直接父类当中的方法 ,和接口当中的方法产生了冲突 , 优先使用父类当中的方法
类与接口之间的关系
1.类与类之间是单继承 其直接父类只能有一个
2.类与接口之间是多实现关系 可以实现多个接口
3.接口与接口之间是多继承关系
注意事项 :
1.多个父接口当中的抽象方法如果重复 , 没关系
2.多个父接口当中的默认方法如果重复 , 那么子接口必须进行默认方法的覆盖重写 ,而且必须带着default关键字
多态性
格式 一句话 左父右子 就是多态
父类名称 对象名 = new 子类对象();
接口名称 对象名 = new 实现类名称();
Final关键字
常见的四种用法
1.可以用来修饰一个类 该类不可以被继承
2.可以用来修饰一个方法 该方法不可以被重写
3.可以用来修饰一个局部变量 局部变量变成常量 , 不可以被改变
4.可以用来修饰一个成员变量 同样和上面的一样
权限修饰符
public表示紧随其后的元素对任何人都是可用的
private表示除类型创建者和类型内部方法之前的任何人都不能访问 如果有人试图访问就会在编译时期得到错误信息
protected 与private作用相当 区别就在于继承的类可以访问protected成员 但是不能访问private成员
默认的访问权限 通常称为包访问权限 类可以随意访问同一个包下的成员 包之外则不可以
内部类的使用
外部类名称 .内部类名称 对象名 =new 外部类名称() .new 内部类名称() ;
内部类的同名变量访问
public class Outter {
int num=10;
public class inner{
int num=20;
public void method(){
int num=30;
System.out.println(num);
System.out.println(this.num);
System.out.println(Outter.this.num);
}
}
}
局部内部类的使用
局部内部类 ,只能在方法中使用 ,出了这个方法 就没法进行使用了
public class Outter {
/*这是在创建一个局部内部类*/
/*局部内部类 ,只能在方法中使用 ,出了这个方法 就没法进行使用了*/
public void methodOut(){
class Inner{
int num =10 ;
public void methodIN(){
System.out.println(num);
System.out.println("韦德");
System.out.println("詹姆斯");
System.out.println("科比");
System.out.println("博士");
}
}
Inner inner=new Inner();
inner.methodIN();
}
}
public class Demo {
public static void main(String[] args) {
Outter outter=new Outter();
outter.methodOut();
}
}
匿名内部类
如果接口的实现类 (或者是父类的子类) 只需要使用唯一的一次 , 那么这种情况下就可以省略掉该类的定义 , 而改为使用[匿名内部类]
格式 :
接口名称 对象名 =new 接口名称 (){
//覆盖重写所有抽象方法
} ;
public interface MyInterface {
public abstract void method();
}
public class MyClass {
public static void main(String[] args) {
MyInterface ms=new MyInterface() {
@Override
public void method() {
System.out.println("这是一个匿名内部类");
}
};
ms.method();
}
}
好处 : 子类不需要实现接口 , 直接创建一个匿名内部类 , 然后对其进行调用方法即可
Objects非空判断
我们可以利用Objects中的方法来进行非空判断
Objects.requiredNonNull(obj); 我们可以利用这个方法来对参数进行非空判断
Objects.requiredNonNull(obj,"传递的对象的值是null");
异常
异常本身也是一个类 , 异常体系
throwable : Error Exception
这是Exception
try{
//可能出现异常的代码
}catch(Exception e){
//出现异常后执行的代码
System.out.println(e);
}
Error
OutofMemoryError:java heap space
内存溢出的错误 , 创建的数组太大了 ,超出了给JVM分配的内存
当出现错误的时候 , 你必须来修改你的代码 , 没有其他的途径可以解决
异常产生过程分析
首先JVM检测出程序会出现异常
JVM会做两件事 : 1.首先创建一个异常对象 , 这个异常对象包含了异常产生的(内容,原因,位置)
2.然后去寻找处理逻辑(try...catch) , 如果没有就继续抛给调用者
main方法接收到了这个异常对象 ,main方法也没有异常的处理逻辑,继续把对象抛给main方法的调用者JVM处理
JVM接收到了这个异常对象,做了两件事
1,把异常对象(内容, 原因,位置)以红色的字体打印在控制台上
2,JVM会终止当前正在执行的java程序 中断处理
JAVA异常处理的五个关键字
try catch finally throw throws
throw关键字
使用格式 : throw是在方法内部中使用的
throw new 异常类名(参数);
例如
throw new NullPointException("要访问的数组不存在");
throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已经超出范围");
throw关键字后边创建的是RuntimeException或者是其子类的对象,我们可以不处理,默认交给JVM处理(打印异常对象 ,中断程序)
throw关键字后边创建的是编译异常(写代码的时候报错) , 我们就必须处理这个异常,要么throws 要么try...catch
Throws关键字 交给别人处理
throw关键字后边创建的是编译异常(写代码的时候报错) , 我们就必须处理这个异常,要么throws 要么try...catch
声明格式:
修饰符 返回值类型 方法名 (参数) throws 异常类名1 , 异常类名2 { }
Try…catch 捕获异常
如果你是throws异常的话 , 遇到异常会立刻终止程序 ,所以我们得处理异常 :
语法 :
try{
编写可能会出现异常的代码
}catch(异常类型 e){
处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}
注意: 1. try 和catch 都不能单独使用, 必须连用
2. catch 可以有多个
Finally 代码块
finally: 在finally中存放的代码一定是会被执行的代码
finally代码示例 :
public class TryCatchDemo4 {
public static void main(String[] args) {
try {
read("a.txt");
} catch (FileNotFoundException e) {
//抓取到的是编译期异常 抛出去的是运行期
throw new RuntimeException(e);
} finally {
System.out.println("不管程序怎样,这里都将会被执行。");
}
System.out.println("over");
}