Java语言学习(一)

写在前面

后端还是Java需求大些,特此学习,由于已有其他语言基础,花了几天仅记录一下自己留意或者模糊的一些方面

命名规范

  1. 类名大驼峰 HelloWorld
  2. 变量名和方法名小驼峰 helloWorld

数据类型

数据类型分类

基本数据类型:

整数型:byte short int(默认) long
浮点型:float double(默认)
字符型:char
布尔型:boolean

引用数据类型:

字符串,数组,类,接口,Lambda…

注意事项:

  1. 字符串是引用类型,不是基本类型
  2. 浮点型是近似值,不精确
  3. 数据范围跟字节数不一定相关,例如:float的4个字节比long8字节表示范围更大,float是用科学计数法存储

数据类型运算

注意事项:

  1. byte/short/char 在进行数字运算时会自动转成int型
    1
    2
    3
    4
    byte num1 = 40;
    byte num2 = 50;
    byte sum1 = num1 + num2;// 报错,因为byte/short/char 在进行数字运算时会自动转成int型
    int sum2 = num1 + num2; // OK
  2. boolean不能发生数据类型转换
  3. 任何数据类型和字符串String进行连接的时候,结果都会变成字符串
  4. 编译器的常量优化
    1
    2
    3
    4
    short a = 5;
    short b = 8;
    short c = a + b; // 报错,需要c为int
    short d = 5 + 8; // OK,因为编译器会在编译后将常量运算5+8替换成13,因为没超过short范围,还会自动加上(short)强制转换
    只会对全是常量的运算优化,如果是short e = 5 + a + 8依旧会报错,因为有a变量

方法的重载Java语言学习(一)

参数个数,参数类型,参数顺序相关
参数名称,返回值类型无关

数组的默认值

整数0,浮点0.0,字符’\u0000’,布尔false,引用null

内存划分

  1. 栈(Stack):方法中的局部变量,方法运行也都是在栈中,一旦超出作用域立刻从栈内存中消失
  2. 堆(Heap):new出来的东西类什么的都在堆中,都附带默认值和地址值
  3. 方法区(Method Area):存储.class相关信息,包含方法的信息
  4. 寄存器(PC Register):与CPU相关
  5. 本地方法栈(Native Method Stack):与操作系统相关

举例:
一个数组的内存图

一个对象的内存图

局部变量和成员变量

  1. 定义位置不一样,局部在方法内部,成员在类内部,方法外部
  2. 默认值不一样,局部无默认值,成员有
  3. 存储位置不一样,局部跟着方法走,在栈中,成员跟着类走,在堆中
  4. 作用域不一样,局部方法外就不能用了,成员全体内部都可以
  5. 生命周期不一样,局部在栈中,方法进栈而诞生,出栈即消失,成员在堆中,对象创建而诞生,对象被垃圾回收即消失

ArrayList泛型

Class ArrayList
E是泛型,只能是引用类型
int >> Integer
char >> Character
除开上面两种其他基本类型都是首字母大写

字符串String

字符串String常量池

只有直接在程序中用写上双引号的字符串才会在堆中字符串常量池,且String实际上用的都是byte数组。
引用类型的==是比较地址值
基本类型==才算是数值的比较
字符串的常量池

字符串常用方法

字符串值的比较

equals即可比较
equalsIgnoreCase忽略大小写
如果是一个常量和一个变量相互比较,推荐把常量放在前面"abc".equals(str);,可以避免str为null时调用equals的空指针异常报错

字符串与获取相关方法

1
2
3
4
public int length()
public String concat(String str)// 返回拼接好的字符串,原字符串不变
public char charAt(int index)// 获取指定位置字符
public int indexOf(String str)// 返回首次出现的索引值,没有返回-1

字符串与截取相关方法

1
2
public String substring(int index)// 从index开始到末尾截取返回
public String substring(int begin, int end)// 截取从begin开始到end结束,包左不包右

字符串与转换相关方法

1
2
3
public char[] toCharArray()// 返回拆分成字符数组
public byte[] getBytes()// 返回拆分字节数组
public String replace(CharSequence oldString, CharSequence newString)// 把所有的老字符替换成新字符,并返回

字符串与分割相关方法

1
public String[] split(String regex)

正则表达中.代表匹配任意字符,如果想.分割的话需要写成\\.

静态Static

  1. 静态不能直接访问非静态,因为内存中先有静态内容后面才有非静态内容的
  2. 静态代码块也要比构造方法先执行,首次用到类会调用,且只会在此调用一次
  3. 静态方法中不能用this
  4. 静态最好用类名来调用

静态数据存储在方法区中的静态区
静态的内存图

Arrays方法

1
2
public static String toString(数组)// 数组转成字符串
public static void sort(数组) // 默认升序排序

Math 数学工具类

1
2
3
4
5
Math.abs()// 取绝对值
Math.ceil()// 向上取整
Math.floor()// 向下取整
Math.round()// 四舍五入,ps:只有他不带小数点,上面三个都带
Math.PI// pai

继承

直接通过子类对象访问成员变量:谁调用谁优先,看等号左边是谁,没有才向上找
间接通过成员方法访问成员变量:方法属于谁,就优先谁,没有才向上找

重写/覆盖

覆盖重写:在继承关系当中,方法的名称一样,参数列表也一样

  1. @Override 加在方法上一行可以检测是否覆盖重写了
  2. 子类的覆盖重写方法的返回值必须【小于等于】父类方法
  3. 子类方法权限必须【大于等于】父类方法 public > protected > (default) > private ps:(default)指什么都不写

父子的构造方法

  1. 子类构造方法中默认会自动调用super(),先执行父类构造方法再是子类
  2. 手动调用父类有参构造的话super(param)必须在子类构造方法中第一行,且只能调用一次。

03-super与this的内存图

抽象类

  1. 抽象类不能创建对象
  2. 抽象类中可以有构造方法,是给子类用的
  3. 抽象类中可以没有抽象方法,但是有抽象方法的必须是抽象类
  4. 抽象类必须覆盖重写所有抽象方法,除非子类还是抽象类

接口

  1. 接口中的成员变量都是常量,都是public static final,必须赋值,且之后不能改变。常量最好是全大写,用下划线分割单词
  2. 接口中最重要的是抽象方法,public abstract 返回值类型 方法名称(参数列表),必须却不覆盖重写,除非子类是抽象类
  3. Java 8 开始,接口中允许定义默认方法,public default 返回值类型 方法名称(参数列表),也可以被覆盖重写
  4. Java 8开始,接口中允许定义静态方法,public static 返回值类型 方法名称(参数列表),【只能用接口名调用,不能用实现类调用,这和继承不一样】
  5. Java 9开始,接口中允许定义私有方法,private 返回值类型 方法名称(参数列表),private static 返回值类型 方法名称(参数列表),注意:private只能接口内部调用,不能被实现类和别人使用。

注意事项

  1. 继承只能唯一父类,接口可以多个同时实现
  2. 接口是没有静态代码块和构造方法的
  3. 多个接口中有重复的抽象方法,只需要实现一次
  4. 多个接口中有冲突的默认方法,必须覆盖重写来解决冲突
  5. 多个接口中的默认方法和父类方法冲突,优先使用父类当中的方法。
  6. 接口可以多继承

多态

就是父左右子,反过来了,范围大的在左边
Fu obj = new Zi();

成员变量

跟继承一样:
直接通过子类对象访问成员变量:谁调用谁优先,看等号左边是谁,没有才向上找
间接通过成员方法访问成员变量:方法属于谁,就优先谁,没有才向上找

1
2
3
Fu obj = new Zi();
obj.num// 成员变量访问的是Fu类的num,即时Zi中也有num
obj.over()// 成员方法如果Zi类覆盖重写了,则用Zi类中的方法,且方法中用的成员变量也是Zi类中的

成员方法

一句话口诀:编译看左,运行看右
指的是编译即写代码时,.出来的东西都只看Fu类,例如:obj.methodZi();就会报错。
运行时看右即,obj.method();优先等号右边的成员方法,找不到才向上找父类

向上转型和向下转型

向上转型就是左父右子,从小范围转为大范围,eg:Animal a = new Cat();
向下转型可以相当于把向下转型【还原】eg:Cat cat = (Cat) a,把进行向上转型成动物的猫向下转型恢复成猫

Instanceof

animal instanceof Cat,检测animal父类引用本来是不是Cat

权限修饰符

publicprotected(default)private
同一个类YYYY
同一个包YYYN
不同包子类YYNN
不同包非子类YNNN

内部类

指在类的内部再定义一个类,注意:内用外,随意用,外用内必须要内部类对象

间接方式:在外部类的方法中使用内部类然后main再调用外部类的方法,曲线救国
直接方法:【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称(); 】

内部类与外部类重名

外部类名称.this.外部类成员变量名,Outer.this.num

类的权限修饰符

  1. 外部类:public protected
  2. 成员内部类:public protected (default) private
  3. 局部内部类:什么都不能写,不是(default)

局部内部类访问所在方法的局部变量

该局部变量必须是事实不变(可以不加final,但是要满足不变)
这是因为方法中的局部变量随着方法入栈而诞生,出栈而消失,但是方法中的类却不会出栈就消失,这就必须要求局部内部类用的方法局部变量不变!

匿名内部类

当接口的实现类(或者是父类的子类)只需要使用唯一一次,则可以用

1
2
3
接口名称 对象名 = new 接口名称(){
//覆盖重写所有抽象方法
};
作者

Yuk

发布于

2022-01-25

更新于

2022-01-25

许可协议

评论