数据类型扩展

整形扩展:

1
2
3
int i=10;//十进制10
int i2=010;//八进制,0开头,此数字表示8
int i3=0x10;//十六进制,0x开头,此数字表示16

浮点数扩展:

浮点数会存在舍入误差(精度丢失),因此无法准确表示。

1
2
3
float a1=0.1f;
float a2=1.0/10;
boolean x=(a1==a2);//x为false

因此尽量避免使用浮点数,永远不要对浮点数进行是否相等的判断

字符扩展:

char类型可以强制转换为整形,其值为对应的ASCII码值

  • 所有的字符本质还是数字
  • char类型使用 Unicode 编码,占两个字节

布尔类型扩展:

在c++中,true,false分别与1,0等价,在Java中不等价

转义字符:

1
2
\t //空格
\n //换行

类型转换

类型由低到高:

Byte——》short——》char——》int——》long——》float——》double

运算时,不同类型的数据会转换成同一类型(转换成最高级的)

  • 类型由低到高,可以发生自动转换
  • 类型由高到低,不能发生自动转换,可以用强制转换
  • 高类型向低类型转换的时候可能存在内存溢出,精度丢失的问题
  • 布尔类型不能发生转换

Java包机制

包的本质是一个文件夹

尽量不要让包里面的名字重复

生成包: package

导入包:import

break,continue和goto

break用于强制退出循环,break后循环不再执行

continue用于结束本次循环,即不再执行后面的语句转而执行下一次循环条件的判断

1
2
3
4
5
6
7
public static void main(String[] arg){
int i=0;
while(i<10){
if(i==5) continue;
System.out.println(i++);
}
}//没有打印5

“goto”:用于从内层循环跳到外层循环,不要使用!!!

先定义标签:标签名+冒号

continue 标签名; break 标签名;

1
2
3
4
5
6
7
8
9
flag:for(int j=0;j<5;j++){
System.out.println("666");

for(int k=0;k<5;k++){
if(k==3) continue flag;

System.out.println(k);
}
}

方法

Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段

  • 是解决一类问题的步骤的有序集合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用

方法的所有部分:

  • 修饰符
  • 返回值类型
  • 方法名
  • 参数类型
  • 方法体

方法重载:

方法重载的规则:

  • 方法名必须相同
  • 参数列表必须不同(类型,个数,顺序)
  • 方法的返回类型不能作为方法重载的依据

遇到方法重载时,编译器会根据调用方法的参数个数、类型、顺序等逐一匹配,调用最适合的方法,如果匹配失败,则编译器报错

可变参数

有时候,无法确定方法的参数有几个时,可以使用可变参数。可变参数在方法中会变成数组

  • 语法:参数类型…参数名
  • 一个方法最多只能有一个可变参数
  • 方法的可变参数在参数列表中要处于其他参数的后面(即最后一个)

示例:

1
2
3
4
5
6
7
8
9
10
public static void main(String[] arg){
forInt(0,1,2,3,4);
}

public static void forInt(int x,int...i){
System.out.println(x);
for(int j=0;j<i.length;j++){
System.out.println(i[j]);
}
}//可变参数要处于最后面

数组

定义数组的语法(一维数组):

数据类型[] 变量名; //声明一个数组

变量名=new 数据类型[数组长度];//创建一个数组

获取数组的长度:数组名.length;

示例:

1
2
3
int[] nums;
nums=new int[10];
int a=nums.length;

数组的三种初始化

静态初始化

1
int[] arr={1,2};

动态初始化

1
int[] nums=new int[10];

默认初始化

1
//动态初始化中包含默认初始化。例如当动态初始化的整形数组为赋值时,默认值为0

二维数组

1
2
3
int[][] nums=new int[1][2];

int[][] arr={{1,2},{1,2,3},{1,2,3,4}};

用户交互Scanner

用Scanner来获取用户输入

  • 使用Scanner要导包:java.util.Scanner
  • 创建一个扫描器对象,用于接收用户的输入
1
2
Scanner sc=new Scanner(System.in);
//创建一个扫描器对象,用于接收键盘的数据
  • 用hasNext()与hasNextline()可以判断是否还有输入的数据

  • 用完scanner,使用.close()关闭Scanner,节省资源

    1
    2
    Scanner sc=new Scanner(System.in);
    sc.close();

Scanner的接收器

  • .next() 接收字符串,遇到空格或回车会停止
  • .nextLine() 接收字符串,可以读取空格,遇到回车停止
  • .nextInt() 接收下一个整数,可以使用hasNextInt()判断输入是否合法
  • .nextFloat() 接收下一个浮点数,可以使用hasNextFloat判断输入是否合法
  • 还有其他很多接收器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] arg){

Scanner sc=new Scanner(System.in);
float a=0.0f;
String b="a";

if(sc.hasNextFloat()){
a=sc.nextFloat();
System.out.println(a);

}else{
System.out.println("数据有误!");
b=sc.nextLine();
System.out.println(b);
}
}
1
2
3
4
输出:
aaaaa
数据有误!
aaaaa

Array类

使用时要导包 import java.util.Arrays

Arrays为静态类,可以不用实例化直接使用

  • .toString(数组名) 打印数组

    1
    2
    3
    4
    public static void main(String[] arg){
    int[] a={1,2,3,1,4,5,6,777,8};
    System.out.println(Arrays.toString(a));
    }

    输出:

    1
    [1, 2, 3, 1, 4, 5, 6, 777, 8]
  • .sort(数组名) 快速排序数组

    1
    2
    3
    4
    5
    public static void main(String[] arg){
    int[] a={1,2,3,1,4,5,6,777,8};
    Arrays.sort(a);
    System.out.println(Arrays.toString(a));
    }

    输出:

    1
    [1, 1, 2, 3, 4, 5, 6, 8, 777]
  • .fill(数组名,开始位置,结束位置,替换的值) 把指定位置替换成指定的值(不指定位置则全部替换)

    1
    2
    3
    4
    5
    public static void main(String[] arg){
    int[] a={1,2,3,1,4,5,6,777,8};
    Arrays.fill(a,0,4,77 );
    System.out.println(Arrays.toString(a));
    }

    输出:

    1
    [77, 77, 77, 77, 4, 5, 6, 777, 8]

Integer类

Integer对象的方法
Integer.parseInt(“”);是将字符串类型转换为int的基础数据类型
Integer.valueOf(“”)是将字符串类型数据转换为Integer对象
Integer.intValue();是将Integer对象中的数据取出,返回一个基础数据类型int

稀疏数组

当一个数组有大量的重复数值(比如0)时,可以使用稀疏数组的结构来储存。

  • 稀疏数组的结构
    • 一个二维数组
    • 第零行存了数组的行数、列数、默认值
    • 从第一行开始,每行存储数组中非默认值的位置的信息(在第几行,在第几列,值为多少)

面向对象之-封装

  • 该藏的藏起来:

    程序设计追求“高内聚,低耦合”。高内聚即类的内部数据操作细节自己完成,不让外部干涉。低耦合即暴露少量的方法给外部使用

  • 封装:即数据的隐藏

    通常,应该禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问

  • 属性私有,通过get/set来操作

利用alt+insert键快速生成get/set方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TrainingCharactor {
public int age;
public String name;

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

面向对象之-继承

  • 继承是类与类之间的关系
  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类),子类继承父类,使用关键字extends来表示
  • 子类和父类之间具有“is a”的关系
  • 父类的构造方法不能被继承!!!
  • 静态方法可以被继承,但无法被重写

ctrl+h可以打开继承关系树

Java中,所有的类都默认继承自Object类

Java中只有单继承!

super()

super()使用实例:子类想要访问父类的方法或属性时,可以使用super.来访问

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A{
protected String name="A";
public void printName(){
System.out.println(name);
}
}

class B extends A{
String name="B";
public void printName(){
System.out.println(this.name);
System.out.println(super.name);//利用super.name来访问父类的name
}
}

super()使用实例:子类的构造方法中

编译器会自动在子类构造函数的第一句加上 super(); 来调用父类的无参构造器;此时可以省略不写。如果想写上的话必须在子类构造函数的第一句。

在子类的构造方法前,会默认地加入父类的无参构造方法super(),此时如果父类定义了有参构造而没有定义无参构造,会报错。

可以通过super来调用父类其他重载的构造方法,只要相应的把参数传过去就好

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A{
protected String name="A";

A(String a){
name=a;
}

public void printName(){
System.out.println(name);
}
}

class B extends A{

String name="B";

public void printName(){
System.out.println(this.name);
System.out.println(super.name);
}
}//会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
class B extends A{

public B(String a){
super(a);
}//通过super来调用父类其他重载的构造方法,把参数传过去就可以

String name="B";

public void printName(){
System.out.println(this.name);
System.out.println(super.name);
}
}

方法重写与重载

重写:

重写的注解:@override

重写的前提:要有继承关系,子类重写父类的方法:

特点:

  1. 方法名必须相同,方法体不同
  2. 参数列表必须相同
  3. 修饰符的范围可以扩大,但不能缩小
  4. 抛出的异常可以被缩小,但不能扩大

静态方法可以被继承,但无法被重写!!!

重载:

方法重载的规则:

  1. 方法名必须相同
  2. 参数列表必须不同
  3. 方法的返回值类型可以相同也可以不同
  4. 仅仅是返回类型不同不足以成为方法重载的条件

方法重载应避免歧义调用!!!

多态

多态是方法的多态,属性没有多态

多态存在的条件

  1. 要有继承关系

  2. 要有方法重写

  3. 父类的引用指向子类对象

程序中类型的最终状态在运行中才会确定,即一种动态编译

举个栗子:去街上买水果,不管是苹果还是西瓜,只要是水果就行,这就是一种多态。

  • 父类型的引用可以引用子类的对象
  • 子类对象可以用在任何需要使用父类对象的地方,这就是多态。

父类型的引用可以指向子类的对象,但一个对象能调用哪些方法主要看左边的引用,和右边关系不大。

instanceof关键字:

可以判断一个对象是什么类型:

1
2
3
4
5
6
7
8
9
public static void m3(Person p3){
if(p3 instanceof Student){
((Student)p3).displayObject();
}else if(p3 instanceof Employee){
((Employee)p3).displayObject();
}else{
System.out.println("是person");
}
}

接口

接口定义的是一组规则,接口只有定义,自己无法写方法

类的定义是用是class,接口的定义是用interface

接口中的所有定义都是抽象的,而且都是public

  • jdk7以前:

    1. 只能定义全局常量和抽象方法:
    2. 在 Java 接口中声明的变量其实都是常量(全局变量),接口中的变量声明,将隐式地声明为public static final 变量(并且只能是 public,用 private 修饰会报编译错误),即常量。
    3. 接口中定义的变量必须初始化。可以省略 public、static 和 final。
    4. 接口中的所有方法都默认是由public abstract修饰的(抽象方法),只能是 public abstract,其他修饰符都会报错。可以省略public和abstract。
  • jdk8:

    1. 除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface InterFace {
public static int age=2;

public static final String name="蔡徐坤";
//需要初始化

public static int getAge() {
return age;
}
//jdk8之后可以定义静态方法,默认方法。

public void sing();
public void jump();
public void rap();
public void playingBusketball();
}

接口必须需要被实现,可以通过类来实现接口,关键字implements

实现了接口的类,就必须重写接口中的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class InterFaceIMPL implements InterFace{
@Override
public void sing() {

}

@Override
public void jump() {

}

@Override
public void rap() {

}

@Override
public void playingBusketball() {

}
}

一个类可以实现多个接口,在接口名后加","再加接口名,这变相实现了Java的多继承。

抽象类

关键词:abstract,栗子:

1
2
3
4
5
public abstract class Circle {
protected final static double PIE=3.14159;
protected double radius;
protected String name;
}

抽象类的构造方法访问修饰符为protected,这也表明抽象类无法被实例化

继承自抽象类的子类,必须实现其继承自抽象类父类的方法,否则这个子类仍然是抽象类

即使子类是抽象的,其父类也可以是具体的,例如Object类。

内部类

内部类就是在一个类里面定义一个类。栗子:A类中定义一个B类,则B类就是A类的内部类。

内部类的种类:

  1. 成员内部类

    • 成员内部类可以直接访问外部类的私有属性、方法
  2. 静态内部类

    • 静态内部类则无法访问外部类的属性和方法,除非外部类的属性和方法也为静态。

      1
      2
      3
      4
      5
      6
      7
      8
      public class classTraining {
      public int a=10;
      public void change(int a){};

      public static class Inner{
      public int innera=a;
      }
      }//错误
      1
      2
      3
      4
      5
      6
      7
      8
      public class classTraining {
      public static int a=10;
      public void change(int a){};

      public static class Inner{
      public int innera=a;
      }
      }//正确
  3. 局部内部类

    在方法中定义的类就是局部内部类

  4. 匿名内部类

    没有引用名称去保存实例化后的对象

Java异常处理

异常机制

异常,英文是“Exception”,指程序运行中出现的意料之外的情况。

  • 检查性异常:例如用户输入错误或打开一个文件但文件不存在。这些异常在编译时不能被简单地忽略。
  • 运行时异常:运行时异常可以在编译时被忽略,这种异常是可以被程序员避免的。
  • 错误:Error,错误是程序脱离控制的问题。例如栈溢出。它们在编译时是检查不到的。

Java中,万物皆对象,Java把异常当成对象来处理,并定义了一个基类:java.lang.Throwable作为所有异常的超类。

Java API中定义了许多异常类,并分为两大类:错误Error和异常Exception。

Error和Exception的区别

Error通常是致命性的错误,当出现Error时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被处理的,并且程序中应尽可能地去处理这些异常。

  • Error

    Error类对象由Java虚拟机生成并抛出。

  • Exception

    Exception分支中有一个重要的子类:RuntimeException,运行时异常。

    ArrayIndexOutOfBoundsException:数组下标越界

    NullPointerException:空指针异常

    ArithmeticException:算术异常,如除数为0

    MissingResourceException:丢失资源

    ClassNotFoundException:找不到类异常

扩展:Java中的异常分类

  • Error:一般是系统出错,是免检异常
  • Exception:
    • ClassNotFoundException:必检异常
    • IOException:必检异常
    • RuntimeException:运行时异常,为免检异常

异常的捕获和抛出

处理异常的方法:

  1. 在方法头中声明异常
  2. 在方法体中抛出异常
  3. try-catch捕获异常

1.在方法头中声明异常

每个方法都必须声明它可能抛出的必检异常的类型,这被称为声明异常

1
public static void main(String[] args) throws Exception

2.在方法体中抛出异常

在一个程序检测一个错误时,可以创建一个恰当的异常类型的实例并抛出它。这被称为抛出异常

1
2
NumberFormatException numberFormatException=new NumberFormatException();
throw numberFormatException;
1
throw new NumberFormatException();

在try-catch块中,捕获的也是一个异常的实例

3.try-catch-finally捕获异常

try语法块里写想要测试的代码

catch语法块里写想要捕获的异常。

  • 用catch捕获多个异常时,大的,范围广的异常应该后捕获,小的,范围窄的异常应该先捕获,否则会报错。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    try {
    System.out.println();
    }catch(NumberFormatException nfe){
    System.out.println("1");
    }catch(Exception exp){
    System.out.println("2");
    }catch(Throwable tra){
    System.out.println("3");
    }

finally语法块写在最后,用于捕获完异常后的处理。不管异常有没有被捕获,finally语法块里的都会执行。

Java文件读写

存储在程序中的数据是暂时的,为了能够永久储存数据,需要存到磁盘中。在Java中,可以用File类来打开并操作一个文件

1
File file = new File(//填入文件路径);

如果文件不存在,可以用.creatNewFile()创建文件

printWriter类:写文件,写完后要.close(),数据才会真正被写入文件

Scanner类:读文件