数据类型总述
基本数据类型
- 分类(4类8种)
- 整数型 byte short int long (1\2\4\8字节)
- 浮点型 float double (4\8字节)
- 字符型 char (2字节)
- 布尔型 boolean
- 注意:
- 数据范围和字节数不一定相关,float(4)数据范围比long(8)更广泛
- 浮点数默认double,若要用float在数字后加F后缀
- 整数默认int,若要用long在数字后加L后缀
数据类型转换
自动类型转换(隐式)
- 特点:自动完成
- 规则:数据范围从小到大
- byte short int long float long
强制类型转换(显式)
- 特点:需要进行特殊处理,无法自动完成
- 格式:小范围类型 变量名 = (小范围类型) 大范围数据;
- 注意:
- 强制类型转换,会导致精度损失(浮点数)、数据溢出(整数)
- byte/short/char三种类型可以进行数***算
- byte/short/char运算时都会被提升成为int(byte/...+char/...->int),char在计算机底层会被翻译成一个数字,再进行运算
- boolean类型不能发生类型转换
引用数据类型
Java内存划分
- 栈(Stack):
- 存放的都是方法中的局部变量,方法一定要在栈中运行
- 局部变量:方法的参数,或者方法{}内部的变量
- 作用域:一旦超出作用域,立刻从栈内存中消失
- 堆(Heap):凡是new出来的东西,都在堆当中
- 堆内存里面的东西都有一个地址值:16进制
- 堆里面的数据都已默认值
- 整数 ---> 0
- 浮点 ---> 0.0
- 字符 ---> '\u0000'
- 布尔 ---> false
- 引用 ---> null
- 方法区(Method Area):存储.class相关信息,包含方法信息
- 本地方法栈(Native Method Stack):与操作系统相关
- 寄存器(pc Register):与CPU相关
数组
- 特点
- 数组中多个数据类型统一
- 长度在程序运行期间不改变
- 数组的初始化:在内存中创建一个数组,并向其中赋予默认值
- 动态初始化(长度)
- 格式:数据类型[] 数组名 = new 数据类型[长度];
- 默认值:0/0.0/'\u0000'/false/null
- 静态初始化(内容)
- 格式:数据类型[] 数组名 = new 数据类型[]{元素....};
- 省略格式(不可拆分两步):数据类型[] 数组名 = {元素....};
- 动态初始化(长度)
- 访问
- 访问格式:数组名[索引];
- 直接打印数组名,得到数组对应内存地址哈希值(Heap中)
- 常见异常
- 索引越界异常:若访问时索引编号不存在,会发生
- 空指针异常:若数组仅赋值null没有进行new创建(引用类型变量可以赋值null,代表其中什么都没有)
- 获取长度:数组名.length;
- 数组作为方法参数/返回值
- 参数:数组作为参数,传递进去的其实是数组的地址值,调用时向方法的小括号传参
- 返回:数组作为返回值,返回的其实也是数组的地址值,一个方法可以有多个参数,但只能有0、1个,不能有多个返回值,需要对多个结果进行返回,应使用一个数组作为返回值类型
字符串
特点:
- 程序中所有的双引号字符串,都是String类的对象(没有new也是)
- 字符串的内容永不可变,因此字符串可以共享使用
- 字符串效果上相当于char[]字符数组,底层原理是byte[]字节数组(数据的最小单位)
创建字符串的常见3+1种方式
三种构造方法:
- public String(); 创建一个空白字符串,不含任何内容
- public String(char[] array); 根据字符数组内容,创建对应的字符串
- public String(byte[] array); 根据字节数组内容,创建对应的字符串
char[] charArray = {'A','B','C'}; byte[] byteArray = {97, 98, 99}; String str1 = new String(charArray); String str2 = new String(byteArray);//abc
一种直接创建:
String str = "Hello";
字符串常量池:(存在堆中)
- 程序中直接创建的双引号字符串,就在字符串常量池中,new的字符串不在常量池中
- == :对于基本类型,==是进行字符串的比较;对于引用类型,==是进行地址值的比较
String类的常用方法
- 比较字符串内容:
- equals():
public boolean equals(Object obj);
- 参数可以是任何对象,只有参数是一个字符串且内容相同的才返回true,否则false
- 注意:
- equals()方法具有对称性
- 比较双方是一个常量一个变量,推荐将常量字符串写前面
"abc".equals(str1);
- str1 = null;时
str1.equals("abc");
会出现空指针异常
- equalsIgnoreCase() 忽略大小写(仅英文字母)
- equals():
- 获取内容相关的方法
- public int length();//获取字符串中含有的字符个数,即长度
- public String concat(String str);//将当前字符串和参数字符串拼接成为返回新字符串
- public char charAt(int index);//获取指定索引位置的单个字符
- public int indexOf(String str);//查找参数字符串在原字符串中第一次出现的索引位置(没找着返回-1)
- 字符串截取方法
- public String substring(int index);//截取从参数索引开始到字符串末尾,返回该新字符串
- public String substring(int begin, int end);//截取[begin,end) 的这一段字符串,并返回
- 字符串转换的相关方法
- public char[] toCharArray();// 将字符串转换成为字符数组
- public byte[] getBytes();// 获得当前字符串底层的字节数组
- public String replace(CharSequence oldString, CharSequence newString);//
- 游戏中骂人文字
String lan2 = lan1.replace("你大爷的","****");
- 游戏中骂人文字
- 字符串分割方法
- public String[] split(String regex);//按照参数规则,将字符串切分成若干部分
- 参数regex是一个正则表达式,如果要按照.进行切割:split("\.");
- 比较字符串内容:
StringBuilder类
- 与String类的区别:
- String类:
- 字符串是常量,值在创建后不能更改,底层是一个被final修饰的数组不能改变
private final byte[] value;
- 字符串相加时,内存中会有多个字符串,占用空间多,效率低
- 字符串是常量,值在创建后不能更改,底层是一个被final修饰的数组不能改变
- StringBuilder类:
- 字符串缓冲区,可以提高字符的操作效率,可看成一个长度可变的字符串
- 底层也是一个数组,没有被final修饰,可以改变长度
byte[] value = new byte[16];
//初始容量16 - StringBuilder在内存中始终是一个数组,占用空间小,效率高
- 若超出StringBuilder的容量会自动扩容
- StringBuilder和String可以相互转换
- String -> StringBuilder 可以使用StringBuilder的构造方法
- StringBuilder -> String 可以使用StringBuilder中的toString方法
- String类:
- 与String类的区别:
基本类型与字符串之间转换
- 基本类型 --> 字符串(String)
- 基本类型的值 + "" :最简单(工作中常用)
static String toString(int i)
:包装类的静态方法toString(参数),不是Object类的toString() 重载static String valueOf(int i)
:String类的静态方法valueOf(参数),返回int参数的字符串表示
- 字符串(String) --> 基本类型
- 使用包装类的静态方法parseXXX("基本数值的字符串");
- static int parseInt(String s);
- ...
- 使用包装类的静态方法parseXXX("基本数值的字符串");
- 基本类型 --> 字符串(String)
用法
- 构造方法:
- 无参构造 * 带字符串构造:
StringBuilder(String str)
- 无参构造 * 带字符串构造:
- 常用方法:
public StringBuilder append(...)
添加 任意类型 数据的字符串形式,并返回当前对象自身public String toString();
:将当前StringBuilder对象转换为String对象
- 构造方法:
接口
概念:
- 接口是多个类的公共规范
- 接口是一种引用数据类型,最重要的内容就是其中的抽象方法
- 注意:接口interface,编译生成的字节码文件依然是:.java ---> .class
格式:public interface 接口名{ ... }
可定义内容:常量、抽象方法(Java 7)、默认方法、静态方法(Java 8)、私有方法(Java 9)
- 抽象方法
- public abstract void methods(){}
- 接口中的抽象方法,修饰符必须是两个固定的关键字:public abstract
- 这两个关键字修饰符,可以选择性省略/全省略
- 方法的三要素可以随意定义
- 默认方法(Java 8开始)
- 格式:
public default 返回值类型 方法名(参数列表){ ...方法体... } //public可省略
- 备注:将接口新添加的方法改为默认方法,可以解决接口升级问题(接口Interface加入了新的抽象方法,实现类来不及更改)
- 使用:
- 接口的默认方法,可以通过接口实现类对象,直接调用
- 接口的默认方法,也可以通过接口的实现类,进行重写(改变了默认的方法体)
- 注实现类调用默认方法,若实现类中没有,则向上找接口
- 格式:
- 静态方法(Java 8开始)
- 格式:
public static 返回值类型 方法名(参数表){...方法体...} //public可省略
- 使用:通过接口名称,直接调用其中的静态方法(与对象无关)
- 格式:接口名.静态方法名(参数表);
- 格式:
- 私有方法(Java 9)
- 目的:抽取一个共有方法,解决两个默认方法之间重复代码的问题,且这个共有方法不让实现类使用,应该私有化
- 解决方案:允许定义私有方法
- 普通私有方法,解决多个默认方法之间重复代码问题
- 格式:
private 返回类型 方法名(参数表){ ... }
- 格式:
- 静态私有方法,解决多个静态方法之间重复代码问题
- 格式:
private static 返回类型 方法名(参数表){ ... }
- 格式:
- 普通私有方法,解决多个默认方法之间重复代码问题
- 常量
- 格式:public static final 数据类型 常量名 = 数据值;
- 注意:
- 一旦用final进行修饰,说明不能改变
- 接口中的常量可以省略public static final三个关键字,不写则默认如此
- 接口中的常量,必须进行赋值,不能不赋值
- 接口中的常量名称,建议使用全大写字母,用下划线进行分隔。
- 使用:接口名.常量名;
- 抽象方法
接口使用步骤
- 接口不能直接使用,必须有一个实现类来实现该接口
- 格式:public class 实现类名称 implements 接口名{ ... }
- 接口的实现类必须覆盖(实现)接口中所有的抽象方法,(去掉abstract,加上方法体)
- 创建实现类的对象,进行使用!(不能直接new接口对象使用)
- 接口不能直接使用,必须有一个实现类来实现该接口
接口使用注意!!
- 接口不能有静态代码块和构造方法
- 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口
public class MyInterfaceImpl implements MyInterfaceA,MyInterfaceB{ //覆盖重写所有抽象方法 }
- 如果实现类所实现的多个接口中,存在重复的抽象方法,那么只需要覆盖一次
- 如果实现类没有覆盖所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类
- 如果实现类所实现的多个接口中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖
- 一个类如果直接父类中的方法,和接口当中的默认方法产生了冲突,则优先用父类中的方法
类与接口的关系
- 类与类之间是单继承的,直接父类只有一个
- 类与接口之间是多实现的,一个类可以实现多个接口
- 接口与接口之间是多继承的
- 注意
- 多个父接口中的抽象方法如果重复,没关系
- 多个父接口中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,而且要带default关键字