Java语言学习(一)
写在前面
后端还是Java需求大些,特此学习,由于已有其他语言基础,花了几天仅记录一下自己留意或者模糊的一些方面
命名规范
- 类名大驼峰 HelloWorld
- 变量名和方法名小驼峰 helloWorld
数据类型
数据类型分类
基本数据类型:
整数型:byte short int(默认) long
浮点型:float double(默认)
字符型:char
布尔型:boolean
引用数据类型:
字符串,数组,类,接口,Lambda…
注意事项:
- 字符串是引用类型,不是基本类型
- 浮点型是近似值,不精确
- 数据范围跟字节数不一定相关,例如:float的4个字节比long8字节表示范围更大,float是用科学计数法存储
数据类型运算
注意事项:
- byte/short/char 在进行数字运算时会自动转成int型
1
2
3
4byte num1 = 40;
byte num2 = 50;
byte sum1 = num1 + num2;// 报错,因为byte/short/char 在进行数字运算时会自动转成int型
int sum2 = num1 + num2; // OK - boolean不能发生数据类型转换
- 任何数据类型和字符串String进行连接的时候,结果都会变成字符串
- 编译器的常量优化只会对全是常量的运算优化,如果是
1
2
3
4short 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
内存划分
- 栈(Stack):方法中的局部变量,方法运行也都是在栈中,一旦超出作用域立刻从栈内存中消失
- 堆(Heap):new出来的东西类什么的都在堆中,都附带默认值和地址值
- 方法区(Method Area):存储.class相关信息,包含方法的信息
- 寄存器(PC Register):与CPU相关
- 本地方法栈(Native Method Stack):与操作系统相关
举例:
局部变量和成员变量
- 定义位置不一样,局部在方法内部,成员在类内部,方法外部
- 默认值不一样,局部无默认值,成员有
- 存储位置不一样,局部跟着方法走,在栈中,成员跟着类走,在堆中
- 作用域不一样,局部方法外就不能用了,成员全体内部都可以
- 生命周期不一样,局部在栈中,方法进栈而诞生,出栈即消失,成员在堆中,对象创建而诞生,对象被垃圾回收即消失
ArrayList泛型
Class ArrayList
E是泛型,只能是引用类型
int >> Integer
char >> Character
除开上面两种其他基本类型都是首字母大写
字符串String
字符串String常量池
只有直接在程序中用写上双引号的字符串才会在堆中字符串常量池,且String实际上用的都是byte数组。
引用类型的==
是比较地址值
基本类型==
才算是数值的比较
字符串常用方法
字符串值的比较
equals即可比较
equalsIgnoreCase忽略大小写
如果是一个常量和一个变量相互比较,推荐把常量放在前面"abc".equals(str);
,可以避免str为null时调用equals的空指针异常报错
字符串与获取相关方法
1 | public int length() |
字符串与截取相关方法
1 | public String substring(int index)// 从index开始到末尾截取返回 |
字符串与转换相关方法
1 | public char[] toCharArray()// 返回拆分成字符数组 |
字符串与分割相关方法
1 | public String[] split(String regex) |
正则表达中.
代表匹配任意字符,如果想.
分割的话需要写成\\.
静态Static
- 静态不能直接访问非静态,因为内存中先有静态内容后面才有非静态内容的
- 静态代码块也要比构造方法先执行,首次用到类会调用,且只会在此调用一次
- 静态方法中不能用this
- 静态最好用类名来调用
静态数据存储在方法区中的静态区
Arrays方法
1 | public static String toString(数组)// 数组转成字符串 |
Math 数学工具类
1 | Math.abs()// 取绝对值 |
继承
直接通过子类对象访问成员变量:谁调用谁优先,看等号左边是谁,没有才向上找
间接通过成员方法访问成员变量:方法属于谁,就优先谁,没有才向上找
重写/覆盖
覆盖重写:在继承关系当中,方法的名称一样,参数列表也一样
@Override
加在方法上一行可以检测是否覆盖重写了- 子类的覆盖重写方法的返回值必须【小于等于】父类方法
- 子类方法权限必须【大于等于】父类方法 public > protected > (default) > private ps:(default)指什么都不写
父子的构造方法
- 子类构造方法中默认会自动调用
super()
,先执行父类构造方法再是子类 - 手动调用父类有参构造的话
super(param)
必须在子类构造方法中第一行,且只能调用一次。
抽象类
- 抽象类不能创建对象
- 抽象类中可以有构造方法,是给子类用的
- 抽象类中可以没有抽象方法,但是有抽象方法的必须是抽象类
- 抽象类必须覆盖重写所有抽象方法,除非子类还是抽象类
接口
- 接口中的成员变量都是常量,都是public static final,必须赋值,且之后不能改变。常量最好是全大写,用下划线分割单词
- 接口中最重要的是抽象方法,public abstract 返回值类型 方法名称(参数列表),必须却不覆盖重写,除非子类是抽象类
- Java 8 开始,接口中允许定义默认方法,public default 返回值类型 方法名称(参数列表),也可以被覆盖重写
- Java 8开始,接口中允许定义静态方法,public static 返回值类型 方法名称(参数列表),【只能用接口名调用,不能用实现类调用,这和继承不一样】
- Java 9开始,接口中允许定义私有方法,private 返回值类型 方法名称(参数列表),private static 返回值类型 方法名称(参数列表),注意:private只能接口内部调用,不能被实现类和别人使用。
注意事项
- 继承只能唯一父类,接口可以多个同时实现
- 接口是没有静态代码块和构造方法的
- 多个接口中有重复的抽象方法,只需要实现一次
- 多个接口中有冲突的默认方法,必须覆盖重写来解决冲突
- 多个接口中的默认方法和父类方法冲突,优先使用父类当中的方法。
- 接口可以多继承
多态
就是父左右子,反过来了,范围大的在左边Fu obj = new Zi();
成员变量
跟继承一样:
直接通过子类对象访问成员变量:谁调用谁优先,看等号左边是谁,没有才向上找
间接通过成员方法访问成员变量:方法属于谁,就优先谁,没有才向上找
1 | Fu obj = new Zi(); |
成员方法
一句话口诀:编译看左,运行看右
指的是编译即写代码时,.
出来的东西都只看Fu类,例如:obj.methodZi();
就会报错。
运行时看右即,obj.method();
优先等号右边的成员方法,找不到才向上找父类
向上转型和向下转型
向上转型就是左父右子,从小范围转为大范围,eg:Animal a = new Cat();
向下转型可以相当于把向下转型【还原】eg:Cat cat = (Cat) a
,把进行向上转型成动物的猫向下转型恢复成猫
Instanceof
animal instanceof Cat
,检测animal父类引用本来是不是Cat
权限修饰符
public | protected | (default) | private | |
---|---|---|---|---|
同一个类 | Y | Y | Y | Y |
同一个包 | Y | Y | Y | N |
不同包子类 | Y | Y | N | N |
不同包非子类 | Y | N | N | N |
内部类
指在类的内部再定义一个类,注意:内用外,随意用,外用内必须要内部类对象
间接方式:在外部类的方法中使用内部类然后main再调用外部类的方法,曲线救国
直接方法:【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称(); 】
内部类与外部类重名
外部类名称.this.外部类成员变量名,Outer.this.num
类的权限修饰符
- 外部类:public protected
- 成员内部类:public protected (default) private
- 局部内部类:什么都不能写,不是(default)
局部内部类访问所在方法的局部变量
该局部变量必须是事实不变(可以不加final,但是要满足不变)
这是因为方法中的局部变量随着方法入栈而诞生,出栈而消失,但是方法中的类却不会出栈就消失,这就必须要求局部内部类用的方法局部变量不变!
匿名内部类
当接口的实现类(或者是父类的子类)只需要使用唯一一次,则可以用
1 | 接口名称 对象名 = new 接口名称(){ |