1. Java数据类型
Java是强类型语言,所有的变量必须先声明后使用,定义变量需要显示的声明一个在编译时就能确定的类型。Java中的数据类型有两种,基本类型(Primitive Type)和引用类型(Reference Type)。
1)基本数据类型
Java基本类型分为两类:数值型和布尔型。数值型可分为整型以及浮点型,整形中的字符型也可单独分为一类。所以一般把基本类型分为4类,如下表:
分类 | 类型 | 长度 |
整数型 | int | 32位 |
long | 64位 | |
short | 16位 | |
byte | 8位 | |
字符型 | char | 16位 |
浮点型 | double | 64位 |
float | 32位 | |
布尔型 | boolean | 1位 |
- 如果一个整数很小(在byte或short)的范围内,当这个整数常量被付给一个byte或short变量时,整数常量会被当作byte或short类型。
- 如果一个巨大的整数常量(超出了Int的存储范围)时,系统不会把这个整数当作long类型处理,除非用户在常量后加上一个字母"L"。
- public class IntegerValTest {
- public static void main(String[] args) {
- //下面代码是正确的,系统会自动把56当成byte类型处理
- byte a = 56;
- /*
- 下面代码是错的,系统不会把9999999999999当成long类型处理,
- 所以超出int的表数范围,从而引起错误
- */
- //long bigValue = 9999999999999;
- //下面代码是正确的,在巨大的整数常量后使用L后缀,强制使用long类型
- long bigValue2 = 9223372036854775807L;
- //以0开头的整数常量是8进制的整数
- int octalValue = 013;
- System.out.println(octalValue);
- //以0x或0X开头的整数常量是16进制的整数
- int hexValue1 = 0x13;
- int hexValue2 = 0XaF;
- System.out.println(hexValue1);
- System.out.println(hexValue2);
- // 定义二个8位的二进制数
- int binVal1 = 0b11010100;
- byte binVal2 = 0b01101001;
- // 定义一个32位的二进制数,最高位是符号位。
- int binVal3 = 0B10000000000000000000000000000011;
- System.out.println(binVal1); // 输出212
- System.out.println(binVal2); // 输出105
- System.out.println(binVal3); // 输出-2147483645
- /*
- 定义一个8位的二进制,该数值默认占32位,因此它是一个正数。
- 只是强制类型转换成byte时产生了溢出,最终导致binVal4变成了-23
- */
- byte binVal4 = (byte)0b11101001;
- /*
- 定义一个32位的二进制数,最好位是符号位。
- 但由于数值后添加了L后缀,因此该整数的实际占64位,第32位的1不是符号位。
- 因此binVal5的值等于2的31次方 + 2 + 1
- */
- long binVal5 = 0B10000000000000000000000000000011L;
- System.out.println(binVal4); // 输出-23
- System.out.println(binVal5); // 输出2147483651
- }
- }
②字符型
字符型用于表示耽搁的字符。字符常量通常用单引号(')括起来。Java使用unicode编码方式,所以字符型变量能够表示大部分国家的文字字符。
字符表示有以下几种方式:
- 直接使用字符常量:如 ‘a’、'我'等。
- 使用转移字符:如'\n'、'\t'等。
- 使用unicode表示字符:如'\uxxxx',其中x表示一个十六进制整数。
如果把一个整数(0~65535之间)常量赋给字符类型变量,系统会把整数当作char处理。
示例:
- public class CharTest {
- public static void main(String[] args) {
- //直接指定单个字符作为字符常量
- char aChar = 'a';
- //使用转义字符来作为字符常量
- char enterChar = '\r';
- //使用Unicode编码值来指定字符常量
- char ch = '\u9999';
- //将输出一个'香'字符
- System.out.println(ch);
- // 定义一个'疯'字符常量
- char zhong = '疯';
- // 直接将一个char变量当成int类型变量使用
- int zhongValue = zhong;
- System.out.println(zhongValue);
- //直接把一个0~65535范围内的int整数赋给一个char变量
- char c = 97;
- System.out.println(c);
- }
- }
Java中浮点型有两种:double和float,两个浮点型的长度分别为64位和32位,且长度不因环境的改变而改变。浮点数的特点是不能够精确的表示一个小数位数较多的小数。
浮点数有两种表示方式:
- 十进制表示:3.11、5.2、4等
- 科学计数法表示:4.12E3、5.12E2;
示例:
- public class FloatTest {
- public static void main(String[] args) {
- float af = 5.2345556f;
- //下面将看到af的值已经发生了改变
- System.out.println(af);
- double a = 0.0;
- double c = Double.NEGATIVE_INFINITY;
- float d = Float.NEGATIVE_INFINITY;
- //看到float和double的负无穷大是相等的。
- System.out.println(c == d);
- //0.0除以0.0将出现非数
- System.out.println(a / a);
- //两个非数之间是不相等的
- System.out.println(a / a == Float.NaN);
- //所有正无穷大都是相等的
- System.out.println(6.0 / 0 == 555.0/0);
- //负数除以0.0得到负无穷大
- System.out.println(-8 / a);
- //下面代码将抛出除以0的异常
- //System.out.println(0 / 0);
- }
- }
④布尔型
布尔型只有一个boolean类型,用于表示逻辑真或者逻辑假。boolean的值只能为true或者是false,其他基本类型不能转换到boolean类型。
示例:
- public class BooleanTest {
- public static void main(String[] args) {
- boolean b1 = true;
- boolean b2 = false;
- //下面代码将出现错误:字符串不能直接变成boolean型的值
- //boolean b3 = "true";
- //使用boolean和字符串进行连接运算,boolean会自动转换成字符串
- String str = true + "";
- //下面将输出true
- System.out.println(str);
- }
- }
2)基本类型之间的转换
Java中基本类型有两种转换方式自动转换和强制转换。讲一个表数范围小的变量赋给一个表数范围大的变量,系统将进行自动转换,将小便量转换为大变量在进行赋值操作。
示例:
- public class AutoPromote {
- public static void main(String[] args) {
- //定义一个short类型变量
- short sValue = 5;
- //下面代码将出错:表达式中的sValue将自动提升到int类型,
- //则右边的表达式类型为int,将一个int类型赋给short类型的变量将发生错误。
- //sValue = sValue - 2;
- byte b = 40;
- char c = 'a';
- int i = 23;
- double d = .314;
- //右边表达式中在最高等级操作数为d(double型)
- //则右边表达式的类型为double型,故赋给一个double型变量
- double result = b + c + i * d;
- //将输出144.222
- System.out.println(result);
- int val = 3;
- //右边表达式中2个操作数都是int,故右边表达式的类型为int
- //因此,虽然23/3不能除尽,依然得到一个int整数
- int intResult = 23 / val;
- //将输出7
- System.out.println(intResult);
- //输出字符串Hello!a7
- System.out.println("Hello!" + 'a' + 7);
- //输出字符串104Hello!
- System.out.println('a' + 7 + "Hello!");
- }
- }
如果系统把大范围变量转换为小范围变量就需要强制转换,强制转换的语法格式是(type)value,可将valae强制转换为type类型的变量。当强制转换可能会导致数据精度的丢失,请看示例:
- public class NarrowConversion {
- public static void main(String[] args) {
- int iValue = 233;
- //强制把一个int类型的值转换为byte类型的值
- byte bValue = (byte)iValue;
- //将输出-23
- System.out.println(bValue);
- double dValue = 3.98;
- //强制把一个double类型的值转换为int
- int tol = (int)dValue;
- // 将输出3
- System.out.println(tol);
- }
- }
3)表达式类型的自动提升
当一个算术表达式中包含多个基本类型时,整个表达式的类型会发生自动提升,Java定义了如下的提升规则:
- 所有的byte类型,short类型和char经提升到int类型。
- 怎个算术表达式的数据类型提升到最高等级操作时的类型。
- public class AutoPromote {
- public static void main(String[] args) {
- //定义一个short类型变量
- short sValue = 5;
- //下面代码将出错:表达式中的sValue将自动提升到int类型,
- //则右边的表达式类型为int,将一个int类型赋给short类型的变量将发生错误。
- //sValue = sValue - 2;
- byte b = 40;
- char c = 'a';
- int i = 23;
- double d = .314;
- //右边表达式中在最高等级操作数为d(double型)
- //则右边表达式的类型为double型,故赋给一个double型变量
- double result = b + c + i * d;
- //将输出144.222
- System.out.println(result);
- int val = 3;
- //右边表达式中2个操作数都是int,故右边表达式的类型为int
- //因此,虽然23/3不能除尽,依然得到一个int整数
- int intResult = 23 / val;
- //将输出7
- System.out.println(intResult);
- //输出字符串Hello!a7
- System.out.println("Hello!" + 'a' + 7);
- //输出字符串104Hello!
- System.out.println('a' + 7 + "Hello!");
- }
- }
2. Java数组的使用
数组是编程语言中最常见的一种数据结构,可以存储多了元素,通常可以通过数组元素的索引来访问数组元素,包括为数组元素赋值和取出数组元素的值。1)数组也是一种类型
- Java中数组要求所包含的元素必须是同一数据类型。在一个数组中,元素的类型时唯一的。一单数组被初始化后,它在内存中占用的空间就确定了,不管数组中是否存放了元素。
- Java的数组也是一种数据类型,是一种引用类型,例如int是一个基本类型,但int[]就是一个引用类型了。
可以使用两种方式定义数组
- type[] arrayName;
- type arrayName[];
3)数组的初始化
Java中的变量都必须先初始化才可以使用。所谓初始化,就是为数组的元素分配内存空间并为每个元素赋初值。
注意:只要为数组元素分配了内存空间,那么元素就一定有一个初始值。
数组的初始化有如下两种方式:
- 静态初始化:初始化时用户显示的指定每个数组元素的初始值,由系统决定数组长度。
- 动态初始化:初始化中用户指定数组长度,由系统为元素分配初始值。
静态初始化的语法如下:
arrayName = new type[]{element1, element2, element3...}type是数组中元素的类型,等号后面的type类型只能是前面和前面type的类型相同或是其子类。
示例:
- //定义一个int数组类型的变量,变量名为intArr.
- int[] intArr;
- //使用静态初始化,初始化数组时只指定数组元素的初始值,不指定数组长度。
- intArr = new int[]{5, 6, 8, 20};
- //定义一个Object数组类型的变量,变量名为objArr.
- Object[] objArr;
- //使用静态初始化,初始化数组时数组元素的类型是
- //定义数组时数组元素类型的子类
- objArr = new String[]{"Java" , "张三"};
- Object[] objArr2;
- //使用静态初始化
- objArr2 = new Object[] {"Java" , "张三"};
arrayName = {element1, element2, element3...}
在这种语法格式中,直接使用花括号定义第一数组:例如
- //数组的定义和初始化同时完成,使用简化的静态初始化写法
- int[] a = {5, 6 , 7, 9};
动态初始化:
动态初始化只指定数组的长度,由系统默认为数组元素赋初值,格式如下:
arrayName = new type[length];
示例:
- //数组的定义和初始化同时完成,使用动态初始化语法
- int[] prices = new int[5];
- //数组的定义和初始化同时完成,初始化数组时元素的类型是定义数组时元素类型的子类
- Object[] books = new String[4];
系统在分配元素的初值时,按一下规则:
- 如元素为基本类型中的整型,默认值为 0;
- 如是基本类型中的浮点型,默认值为 0.0;
- 如实基本类型中的字符型,默认值为 '\u0000';
- 如实基本类型中的布尔型,默认值为 false;
- 如是引用类型,默认值为 null;
4)使用数组
创建一个数组后,可通过数组下表访问(从0开始),可使用for循环来遍历数组元素,也可使用更简洁的foreach进行遍历。
示例:
- public class ForEachErrorTest {
- public static void main(String[] args) {
- String[] books = {"高等数学" ,
- "大学英语",
- "大学物理"};
- //使用foreach循环来遍历数组元素,其中book将会自动迭代每个数组元素
- for (String book : books)
- {
- book = "高等数学";
- System.out.println(book);
- }
- System.out.println(books[0]);
- }
- }
5)深入数组
数组变量是引用类型,它指向内存中数组区域的第一个元素。数组元素和数组变量在内存中是分开存放的。实际的数组对象存储在堆内存中,如果引用该数组的引用变量是一个局部变量,那么它被存放在栈内存中。如下图所示:
只要类型相互兼容,就可以让一个数组指向另一个实际的数组,如下所示:
- public class ArrayInRam {
- public static void main(String[] args) {
- //定义并初始化数组,使用静态初始化
- int[] a = {5, 7 , 20};
- //定义并初始化数组,使用动态初始化
- int[] b = new int[4];
- //输出b数组的长度
- System.out.println("b数组的长度为:" + b.length);
- //循环输出a数组的元素
- for (int i = 0 ,len = a.length; i < len ; i++ ) {
- System.out.println(a[i]);
- }
- //循环输出b数组的元素
- for (int i = 0 , len = b.length; i < len ; i++ ) {
- System.out.println(b[i]);
- }
- //因为a是int[]类型,b也是int[]类型,所以可以将a的值赋给b。
- //也就是让b引用指向a引用指向的数组
- b = a;
- //再次输出b数组的长度
- System.out.println("b数组的长度为:" + b.length);
- }
- }
3、封装
1)private私有;
2)public 公有;(set设置、get查看)
3)static修饰符
static可以修饰成员变量和成员函数
①static成员变量:
- 被所有对象共享,只有一份副本
- 通过“对象名”或“类名”都可以访问
- static的成员变量是在当我们第一次使用该类时,首先被存储在静态区内。在没有此类对象的情况下,就已经存在了。
- 静态成员变量只有一份拷贝,任何对象修改后,其他对象看到的都是新值
2)static 成员函数
- 可以将一个方法声明为static
- 静态方法在没有类对象的情况下就产生了
- 可以通过类名调用,也可以通过对象名调用
- 静态的方法不能访问非静态的成员变量。因为静态方法在没有对象存在的情况下就已经先期存在,但是此时没有任何对象存在,也就没有对象的成员变量空间和值,所以,无法访问
static成员函数应用:
- 经常在一个类中定义若干多的静态方法,例如:求三个数的最大值,还有对数组排序等等
- 供整个项目共享,通过类名可以直接使用
3)static(静态)初始化代码块
- 使用static定义代码块,当第一次使用该类、或访问该类成员时,执行一次, 且只执行一次
- 静态初始化代码块只能访问静态成员变量、调用静态成员方法
4. 继承extends
1.当我们面向对象设计时,会发现一些已抽取的类中,有一些相同的属性或方法。这时我们可以对这些具有重复属性或方法的类进行进一步抽取。
2.将抽取后的类,作为基类,可以被其他类“继承”,达到一个“重用” 的目的
3.一个类“继承”其他类,使用关键字extends
继承的特点:
- Java只支持单继承,不支持多继承
- Java允许多级继承
- 不要仅为了获取其他类中某个功能而去继承
类与类之间的关系:(UML)
1.继承关系(is a)(一般关系):子类继承父类
2.关联关系(has a有一个,多个):例如:学员类和科目类(学员要有一个科目)
3.组合关系:一个类,有多个其他类组成的。
4.依赖关系:一般在类中不持有另外一个类的引用,但是某些方法需要另外类型的引用 这时、这个类依赖于参数类
Super关键字/函数的重写
1.子类定义了跟父类同名的成员变量,这时、这个变量将覆盖(隐藏)了父的同名变量
2.在子类中,可以使用super关键字显示的调用父类被隐藏的成员变量
访问修饰符:private(私有的)-> 默认 ->protected(受保护的)->public(公共的)
函数的重写(Override)(覆盖、重写)
1.子类中可以出现跟父类一样的方法,这时就是:函数的重写
1).返回值类型 方法名参数列表:完全相同
2).访问修饰符:子类重写父类的方法时,访问修饰符必须同重写的方法一致,或更宽的访问修饰符(不包括private)
2.1).编译时,检查如果方法名、参数列表相同,返回值不同将出现编译错误
2.2).如果返回值类型、方法名相同,参数列表不同,可以编译运行, 这个是子类特有的方法,和父类show()方法没有关系
2.private方法不能被重写:
1).子类可以定义一个和父类相同的private的方法,但这不是“重写”, 各自独立的。(即两边都是私有的)
5. 多态
多态的特点
1.成员变量:父类访问的变量始终是父类自己的(对于父类自己的变量及被覆 盖的变量)
2.成员方法:编译的时候看父类中是否有方法,如果没有,编译错误,运行的时候是子类的方法
3.静态方法:被覆盖的静态成员,访问的是父类的。一般情况下,多态性访问的都是父类的,父类有,则编译通过,否则编译失 败 有一个特殊,对于被覆盖的成员方法,运行时是子类的,父类引用,不能访问子类特有的成员