Java基础总结(上)

1 Java基础语法

package Test;
import java.lang.System;
public class Part { 						//新建类Part
	static final double PI = 3.14;
	static int age = 23; 					//声明int型变量age并进行赋值
	
	public static void main(String[] args) { 	//主方法
		final int number; 				//声明int型常量number
		number = 1235; 				//对常量进行赋值
		age = 22; 					//再次对变量进行赋值
		number = 1236; 				//错误的代码,因为number为常量,只能进行一次赋值
		System.out.println("常量PI的值为:" + PI); 			//将PI的值输出
		System.out.println("赋值后number的值为:" +number);	//将number的值输出
		System.out.println("int型变量age的值为:" + age); 	//将age的值输出
	}
}

主类结构
1、包声明:package关键字声明该类所在的包
2、声明变量
3、编写主要方法
4、导入API库:通过import关键字导入相关类

注释
单行注释格式: // 注释文字
多行注释格式: /* 注释文字 /
文档注释格式:/
* 注释文字 */

package com.patrick.pojo;

public class Person {
	private String name;
	private int age;
	
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	
	public String getName() {
		return name;
	}


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

	public int getAge() {
		return age;
	}

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



	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

1.1 数据类型

1.1.1 基本数据类型

Java语言提供了八种基本类型。六种数字类型(四个整数型:byte、short、int、long,两个浮点型:float、double),一种字符类型(char),还有一种布尔型(boolean)。

byte 数据类型是8位、有符号的,以二进制补码表示的整数;
最小值是 -128(-2^7);
最大值是 127(2^7-1);
默认值是 0;
byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;

short 数据类型是 16 位、有符号的以二进制补码表示的整数
最小值是 -32768(-2^15);
最大值是 32767(2^15 - 1);
Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
默认值是 0;

int 数据类型是32位、有符号的以二进制补码表示的整数;
最小值是 -2,147,483,648(-2^31);
最大值是 2,147,483,647(2^31 - 1);
一般地整型变量默认为 int 类型;
默认值是 0 ;

long 数据类型是 64 位、有符号的以二进制补码表示的整数;
最小值是 -9,223,372,036,854,775,808(-2^63);
最大值是 9,223,372,036,854,775,807(2^63 -1);
这种类型主要使用在需要比较大整数的系统上;
默认值是 0L;

float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
float 在储存大型浮点数组的时候可节省内存空间;
默认值是 0.0f;
浮点数不能用来表示精确的值,如货币;

double 数据类型是双精度、64 位、符合 IEEE 754 标准的浮点数;
浮点数的默认类型为 double 类型;
double类型同样不能表示精确的值,如货币;货币用BigDecimal表示

boolean数据类型表示一位的信息;
只有两个取值:true 和 false;
这种类型只作为一种标志来记录 true/false 情况;
默认值是 false;

char 类型是一个单一的 16 位 Unicode 字符;
最小值是 \u0000(十进制等效值为 0);
最大值是 \uffff(即为 65535);
char 数据类型可以储存任何字符;

转义字符

转义字符含义转义字符含义
\ddd1-3位八进制数,比如\123\r回车
\uxxxx4位十六进制数,比如\u0052\n换行
单引号字符\b退格
\反斜杠字符\f换页
\t垂直制表字符,将光标移到下一个制表符的位置

UTF-8

1.1.2 引用数据类型

类、接口、数组

1.1.3 类型转换

自动类型转换
整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。
转换从低级到高级。
必须满足转换前的数据类型的位数要低于转换后的数据类型,例如: short数据类型的位数为16位,就可以自动转换位数为32的int类型,同样float数据类型的位数为32,可以自动转换为64位的double类型。

强制类型转换
条件是转换的数据类型必须是兼容的。
格式:(type)value type是要强制类型转换后的数据类型

int i1 = 123;
byte b = (byte)i1;//强制类型转换为byte

1.2 变量与常量

声明变量

int age;//声明int类型变量
char char1='r';//声明char类型变量并赋值

1.2.1 关键字

在JAVA中目前一共有53个关键字:其中由51+2个保留字=53个关键字

1、JAVA的保留关键字(2个)
const——常量,常数:用于修改字段或局部变量的声明。
goto——转到:指定跳转到标签,找到标签后,程序将处理从下一行开始的命令

2、访问修饰符的关键字(3个)
public (公有的):可跨包
protected (受保护的):当前包内可用
private (私有的):当前类可用
3、定义类、接口、抽象类和实现接口、继承类的关键字、实例化对象(6个)
class (类):public class A(){}花括号里是已实现的方法体,类名需要与文件名相同
interface (接口):public interface B(){}花括号里有方法体,但没有实现,方法体句子后面是英文分号;结尾
abstract (声明抽象):public abstract class C(){}介于类与接口中间,可以有,也可以没有已经实现的方法体
implemenst (实现):用于类或接口,实现接口public class A interface B(){}
extends (继承):用于类继承类public class A extends D(){}
new (创建新对象):A a=new A();A表示一个类

4、包的关键字(2个)
import (引入包的关键字):当使用某个包的一些类时,仅需要类名,然后使用ctrl+shift+o或者选定类名(类或属性或方法)按住ctrl+单击,即可自动插入类所在的包
package (定义包的关键字):将所有相关的类放在一个包类以便查找修改等

5、数据类型的关键字(12个)
byte (字节型):8bit
char (字节型):16bit
boolean (布尔型):–
short (短整型):16bit
int (整型):32bit
float (浮点型):32bit
long (长整型):64bit
double (双精度):64bit
void (无返回):public void A(){}其他需要反回的经常与return连用
null (空值)
true (真)
false (假)

6、条件循环(流程控制)(12个)
if (如果) :if(条件语句{执行代码}如果条件语句成立,就开始执行{}里面的内容
else (否则,或者) :常与if连用,用法相同:if(…){…}else{…}
while (当什么时候):while(条件语句){执行代码}
for(满足三个条件时):for(初始化循环变量;判断条件;循环变量值{}
switch (选择结构):switch(表达式){case 常量表达式1:语句1;…case 常量表达式2;语句2;default:语句;}default就是如果没有匹配的case就执行它,default并不是必须的。case后的语句可以不用大括号。
case (匹配switch的表达式里的结果) :同上
default (默认): default就是如果没有匹配的case就执行它, default并不是必须的
do (运行) :通长与while连用
break (跳出循环):直接跳出循环,执行循环体后的代码
continue (继续) : 中断本次循环,并开始下一轮循环
return (返回) :return 一个返回值类型
instanceof(实例):一个二元操作符,和==、>、<是同一类的。测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据

7、修饰方法、类、属性和变量(9个)
static(静态的):属性和方法都可以用static修饰,直接使用类名、属性和方法名。只有内部类可以使用static关键字修饰,调用直接使用类名、内部类类名进行调用。static可以独立存在
final(最终的不可被改变):方法和类都可用final来修饰;final修饰的类是不能被继承的;final修饰的方法是不能被子类重写。常量的定义:final修饰的属性就是常量
super(调用父类的方法):常见public void paint(Graphics g){super.paint(g);…}
this(当前类的父类的对象):调用当前类中的方法(表示调用这个方法的对象)this.addActionListener(al):等等
native(本地)
strictfp(严格,精准)
synchronized(线程,同步):一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块
transient(短暂)
volatile(易失)

8、错误处理(5个)

catch:处理异常
try:捕获异常
finally:有没有异常都执行
throw:抛出一个异常对象
throws:声明一个异常可能被抛出

9、其他(2个)
enum(枚举,列举,型别)
assert(断言)

this关键字
this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针
1、普通的直接引用,this相当于是指向当前对象本身。
2、 形参与成员名字重名,用this来区分:

public Person(String name, int age) {
    this.name = name;
    this.age = age;
}

3、引用本类的构造函数

class Person{
    private String name;
    private int age;
    
    public Person() {
    }
 
    public Person(String name) {
        this.name = name;
    }
    public Person(String name, int age) {
        this(name);
        this.age = age;
    }
}

super关键字

super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。

子类继承父类之后,在子类中可以使用this来表示访问或调用子类中的属性或方法,使用super
就表示访问或调用父类中的属性和方法。

super也有三种用法:
①. 普通的直接引用
与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。
②. 子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分

class Person{
    protected String name;
 
    public Person(String name) {
        this.name = name;
    }
 
}
 
class Student extends Person{
    private String name;
 
    public Student(String name, String name1) {
        super(name);
        this.name = name1;
    }
 
    public void getInfo(){
        System.out.println(this.name);      //Child
        System.out.println(super.name);     //Father
    }
 
}
 
public class Test {
    public static void main(String[] args) {
       Student s1 = new Student("Father","Child");
       s1.getInfo();
 
    }
}

③. 引用父类构造函数
super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

this与super的区别
super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
super()和this()均需放在构造方法内第一行。
尽管可以用this调用一个构造器,但却不能调用两个。
this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。

1.2.2 常量

在 Java 中使用 final 关键字来修饰常量,声明方式和变量类似

final double PI = 3.1415927;

1.2.3 变量

type identifier [ = value][, identifier [= value] ...] ;

type为Java数据类型。identifier是变量名。可以使用逗号隔开来声明多个同类型变量。

变量类型
Java语言支持的变量类型有:
类变量:独立于方法之外的变量,用 static 修饰。
类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。
静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
静态变量在第一次被访问时创建,在程序结束时销毁。
与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。
默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
静态变量可以通过:ClassName.VariableName的方式访问。
类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。

实例变量:独立于方法之外的变量,不过没有 static 修饰。
实例变量声明在一个类中,但在方法、构造方法和语句块之外;
当一个对象被实例化之后,每个实例变量的值就跟着确定;
实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息;
实例变量可以声明在使用前或者使用后;
访问修饰符可以修饰实例变量;
实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见;
实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;
实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName。

局部变量:类的方法中的变量。
局部变量声明在方法、构造方法或者语句块中;
局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
访问修饰符不能用于局部变量;
局部变量只在声明它的方法、构造方法或者语句块中可见;
局部变量是在栈上分配的。
局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。

public class Variable{
    static int allClicks=0;    // 类变量
    String str="hello world";  // 实例变量
    public void method(){
        int i =0;  // 局部变量
    }
}

1.2.4 修饰符

public : 对所有类可见。使用对象:类、接口、变量、方法

protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。

private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

|修饰符|当前类| 同一包内 |子孙类(同一包) |子孙类(不同包)| 其他包
|–|–|–|–|–|–|–|–|
|public|√|√|√|√|√|
|protected|√|√|√|√/×|×
|default|√|√|√|×|×
|privat|√|×|×|×|×

受保护的访问修饰符-protected
子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;
子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。

1.2.5 运算符

赋值运算符

算术运算符

关系运算符

逻辑运算符

位运算符

条件运算符

扩展运算符

public static void main(String[] args) {
    /*
    * ++ 自增
    * --自减*/
    int a= 3;
    System.out.println("a:"+a);
    int b = a++; // 执行完这行代码后,先给b赋值,再自增
    int c = ++a; // 执行完这行代码前,先自增,再给c赋值

    System.out.println("b:"+b);
    System.out.println("c:"+c);

    // 幂运算
    double pow = Math.pow(3,2);
    System.out.println(pow);
}
位运算
/*位运算
*   2*8 = 16 2*2*2*2
* << 左移 *2
* >> 右移 / 2
* */
System.out.println("左移:"+(2<<3));
System.out.println("右移:"+(2>>3));
System.out.println("左移:"+(8<<3));
/*
* 左移:16
右移:0
左移:64*/
三元运算符
// 三元运算符
public static void main(String[] args) {
    // x ? y:z
    // 如果x == true,则结果为y,否则结果为z
 /*   int score = 100;
    String type = score < 60 ? "不及格" : "及格";  // 必须掌握
    System.out.println(type);*/
    int age = 15;
    String condition = age >30 ? "老了,老了" : "还年轻";
    System.out.println(condition);
}

1.3 流程控制

用户交互Scanner

public static void main(String[] args) {
	//创建一个扫描器对象,用于接收键盘数据
	Scanner scanner = new Scanner(System.in);
	//next方式接收字符串
	System.out.println("Next方式接收:");
	//判断用户还有没有输入字符
	if (scanner.hasNext()){
		String str = scanner.next();
		System.out.println("输入内容:"+str);
	}
	//凡是属于IO流的类如果不关闭会一直占用资源.要养成好习惯用完就关掉.
	scanner.close();
}
public static void main(String[] args) {
	Scanner scan = new Scanner(System.in);
	// 从键盘接收数据
	// nextLine方式接收字符串
	System.out.println("nextLine方式接收:");
	// 判断是否还有输入
	if (scan.hasNextLine()) {
		String str2 = scan.nextLine();
		System.out.println("输入内容:" + str2);
	}
	scan.close();
}

两者区别:
next():
1、一定要读取到有效字符后才可以结束输入。
2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
4、next() 不能得到带有空格的字符串。
nextLine():
1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
2、可以获得空白

1.3.1 复合语句

复合语句为局部变量创建作用域

1.3.2 条件语句

Created with Raphaël 2.3.0 开始 条件表达式 操作1 结束 操作2 yes no

1、if单选择

if(布尔表达式)
{
   //如果布尔表达式为true将执行的语句
}

2、if双选择结构
if…else…

if(布尔表达式){
   //如果布尔表达式的值为true
}else{
   //如果布尔表达式的值为false
}

3、if多选择结构

if(布尔表达式 1){
   //如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
   //如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
   //如果布尔表达式 3的值为true执行代码
}else {
   //如果以上布尔表达式都不为true执行代码
}

4、嵌套的if结构

if(布尔表达式 1){
   如果布尔表达式 1的值为true执行代码
   if(布尔表达式 2){
      如果布尔表达式 2的值为true执行代码
   }
}

5、switch case

switch(expression){
    case value :
       //语句
       break;//记得break,不然会穿透
    case value :
       //语句
       break; 
    //你可以有任意数量的case语句
    default : //可选
       //语句
}

1.3.2 循环语句

1、while 循环

while( 布尔表达式 ) {
  //循环内容
}

2、do…while 循环

do {
       //代码语句
}while(布尔表达式);

3、for 循环

for(初始化; 布尔表达式; 更新) {
    //代码语句
}

跳出循环
break 跳出总上一层循环,不再执行循环(结束当前的循环体)

continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)

return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)

1.4 数组

1.4.1数组

声明数组

dataType[] arrayRefVar;   // 首选的方法
或
dataType arrayRefVar[];  // 效果相同,但不是首选方法

创建数组

arrayRefVar = new dataType[arraySize];

for-each循环

for(type element: array)
{
    System.out.println(element);
}

1.4.2 数组操作

1、遍历


public class Trap { // 创建类
	public static void main(String[] args) { // 主方法
		int b[][] = new int[][] { { 1 }, { 2, 3 }, { 4, 5, 6 } }; // 定义二维数组
		for (int k = 0; k < b.length; k++) {
			for (int c = 0; c < b[k].length; c++) { // 循环遍历二维数组中的每个元素
				System.out.print(b[k][c]); // 将数组中的元素输出
			}
			System.out.println(); // 输出空格
		}
	}
}


public class Tautog { // 创建类
	public static void main(String[] args) { // 主方法
		int arr2[][] = { { 4, 3 }, { 1, 2 } }; // 定义二维数组
		System.out.println("数组中的元素是:"); // 提示信息
		int i = 0; // 外层循环计数器变量
		for (int x[] : arr2) { // 外层循环变量为一维数组
			i++; // 外层计数器递增
			int j = 0; // 内层循环计数器
			for (int e : x) { // 循环遍历每一个数组元素
				j++; // 内层计数器递增
				if (i == arr2.length && j == x.length) { // 判断变量是二维数组中的最后一个元素
					System.out.print(e); // 输出二维数组的最后一个元素
				} else
					// 如果不是二维数组中的最后一个元素
					System.out.print(e + "、"); // 输出信息
			}
		}
	}
}

2、填充替换数组元素

import java.util.Arrays; //导入java.util.Arrays类

public class Swap { // 创建类
	public static void main(String[] args) { // 主方法
		int arr[] = new int[5]; // 创建int型数组
		Arrays.fill(arr, 8); // 使用同一个值对数组进行填充
		for (int i = 0; i < arr.length; i++) { // 循环遍历数组中的元素
			// 将数组中的元素依次输出
			System.out.println("第" + i + "个元素是:" + arr[i]);
		}
	}
}

import java.util.Arrays; //导入java.util.Arrays类

public class Displace { // 创建类
	public static void main(String[] args) { // 主方法
		int arr[] = new int[] { 45, 12, 2, 10 }; // 定义并初始化int型数组arr
		Arrays.fill(arr, 1, 2, 8); // 使用fill()方法对数组进行初始化
		for (int i = 0; i < arr.length; i++) { // 循环遍历数组中的元素
			// 将数组中的每个元素输出
			System.out.println("第" + i + "个元素是:" + arr[i]);
		}
	}
}

3、数组排序

import java.util.Arrays; //导入java.util.Arrays类

public class Taxis { // 创建类
	public static void main(String[] args) { // 主方法
		int arr[] = new int[] { 23, 42, 12, 8 }; // 声明数组
		Arrays.sort(arr); // 将数组进行排序
		for (int i = 0; i < arr.length; i++) { // 循环遍历排序后的数组
			System.out.println(arr[i]); // 将排序后数组中的各个元素输出
		}
	}
}

4、复制数组

import java.util.Arrays; //导入java.util.Arrays类

public class Cope { // 创建类
	public static void main(String[] args) { // 主方法
		int arr[] = new int[] { 23, 42, 12 }; // 定义数组
		int newarr[] = Arrays.copyOf(arr, 5); // 复制数组arr
		for (int i = 0; i < newarr.length; i++) { // 循环变量复制后的新数组
			System.out.println(newarr[i]); // 将新数组输出
		}
	}
}

import java.util.Arrays; //导入java.util.Arrays

public class Repeat { // 创建类
	public static void main(String[] args) { // 主方法
		int arr[] = new int[] { 23, 42, 12, 84, 10 }; // 定义数组
		int newarr[] = Arrays.copyOfRange(arr, 0, 3); // 复制数组
		for (int i = 0; i < newarr.length; i++) { // 循环遍历复制后的新数组
			System.out.println(newarr[i]); // 将新数组中的每个元素输出
		}
	}
}

5、查询数组

import java.util.Arrays; //导入java.util.Arrays类

public class Example { // 创建类
	public static void main(String[] args) { // 主方法
		int ia[] = new int[] { 1, 8, 9, 4, 5 }; // 定义int型数组ia
		Arrays.sort(ia); // 将数组进行排序
		int index = Arrays.binarySearch(ia, 4); // 查找数组ia中元素4的索引位置
		System.out.println("4的索引位置是:" + index); // 将索引输出
	}
}

1.5 Java基本算法实现

1.5.1 排序

冒泡排序
选择排序
插入排序
希尔排序
归并排序
快速排序
堆排序
计数排序
桶排序
基数排序

1.5.2 查找

顺序
二分
插值

1.5.3 动态规划

1.5.4 分治算法

1.5.5 回溯算法

1.5.6 贪心算法

2 面向对象

面向对象(Object Oriented Programming,OOP)程序设计中替代面向过程(Procedure Oriented Programming,POP)程序设计的一种程序设计方法。面向对象是一种程序的设计范型,是一种思想,使用 对象 的概念进行程序设计。

2.1 类和对象

2.1.1 类和对象

类是具有相同的特征和行为的一组对象的抽象

class 类名 { 
	//成员属性;
	public    公有成员;
	protected 保护成员;
	private   私有成员;
	default  默认成员;
	
	//构造方法;
	
	//成员方法;
}

对象是类的实例
对象是根据类创建的,并且一个类可以对应多个对象。

//创建对象
// 方式1 
类名 对象名=new 类名(); 
// 方式2 
类名 对象名; 对象名=new 类名();

//访问对象
//访问对象的属性
对象名.属性名
//访问对象的方法
对象名.方法名()

this关键字和super关键字
可以使用this关键字来解决局部变量和全局变量同名的问题
this代表所在类的对象引用
this表示当前类的一个对象(方法被哪个对象调用,this就代表那个对象),只能在类的方法中使用,表示方法的调用者,即调用该方法的对象 当局部变量和全局变量同名时,可以使用 this。来访问全局变量 当局部变量和全局变量不同名时,可以省略不写 this。

super是一个指代变量,用于在子类中指代父类对象。是super指代的是一个父类的对象,它需要在运行时被创建,而静态方法是类方法,它是类的一部分。当类被加载时,方法已经存在,但是这时候父类对象还没有被初始化。
在子类中调用父类的属性或方法。特别是子类中有与父类相同的属性或者方法,那么这时如果你想调用父类的属性或者方法,那么你必须使用super关键字。因为子类中和父类中的属性或方法同名,则父类中的方法或属性将被覆盖或隐藏。super可以指代父类中的类属性和类方法,但是并不建议这么用,虽然不会报错,但是说明对static关键字还不够了解。

2.1.2 包和内部类

Java类包
java不允许同名的类文件,需要把它们放在不同的包中

内部类
在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类。内部类本身就是类的一个属性,与其他属性定义方式一致。
内部类可以分为四种:成员内部类、局部内部类、匿名内部类和静态内部类。

成员内部类

class OutClass{//外部类
	class InnerClass{//内部类
	}
}

在一个类中使用内部类,,内部类可以随意使用外部类的成员方法和成员变量

内部类的实例一定要绑定在外部类的实例上

public class Car {							 // 创建汽车类
	private String brand; 					 // 汽车品牌
	public Car(String brand) {				 // 汽车类的构造方法,参数为汽车品牌
		this.brand = brand; 					 // 给汽车品牌赋值
	}
	class Engine {							 // 发动机类(内部类)
		String model; 						 // 发动机型号
		public Engine(String model) {			 // 发动机类的构造方法,参数为发动机型号
			this.model = model; 				 // 给发动机型号赋值
		}
		public void ignite() {				 // (发动机)点火方法
			System.out.println("发动机" + this.model + "点火");
		}
	}
	public void start() {						 // 启动(汽车)方法
		System.out.println("启动" + this.brand);
	}
	public static void main(String[] args) {
		Car car = new Car("大众朗行");			 // 创建汽车类对象,并为汽车品牌赋值
		car.start();							 // 汽车类对象调用启动(汽车)方法
		// 创建发动机类(内部类)对象,并为发动机型号赋值
		Car.Engine engine = car.new Engine("EA211");
		engine.ignite();						 // 发动机类对象调用(发动机)点火方法
	}
}

局部内部类

定义在方法中的内部类,就是局部内部类。
匿名内部类

new/接口{ 
  //匿名内部类实现部分
}

静态内部类
定义在类内部的静态类,就是静态内部类。

静态内部类可以访问外部类所有的静态变量,而不可访问外部类的非静态变量;静态内部类的创建方式,new 外部类.静态内部类()。

内部类的优点
一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
内部类不为同一包的其他类所见,具有很好的封装性;
内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
匿名内部类可以很方便的定义回调。
内部类的应用场景
一些多算法场合
解决一些非面向对象的语句块。
适当使用内部类,使得代码更加灵活和富有扩展性。
当某个类除了它的外部类,不再被其他的类使用时。

2.1.3 方法调用

静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。

实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。

在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制

注意:由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。



public class StaticDemo {
	static double PI = 3.1415; // 在类中定义静态常量

	public static void method() { // 在类中定义静态方法
		System.out.println("这是静态方法");
	}

	public static void main(String[] args) {
		System.out.println(StaticDemo.PI); // 调用静态常量
		StaticDemo.method(); // 调用静态方法
	}
}


public class NonStaticDemo {

	public void method() { // 在类中定义非静态方法
		System.out.println("这是非静态方法");
	}

	public static void main(String[] args) {
		NonStaticDemo s = new NonStaticDemo;//使用new关键字创建对象
		s.method(); // 调用非静态方法
	}
}

2.1.4 构造器

类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下俩个特点:

  1. 必须和类的名字相同
  2. 必须没有返回类型,也不能写void

构造器的作用:

  1. 使用new创建对象的时候必须使用类的构造器
  2. 构造器中的代码执行后,可以给对象中的属性初始化赋值
public class People {
	String name;
	int age;
	String sex;

	//无参构造
	public People() {
	}
	//有参构造
	public People(String name, int age, String sex) {
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	public static void main(String[] args) {
		People p1 = new People("tom", 23, "男");
		People p2 = new People("lily", 19, "女");
	}
}

在java中,即使我们在编写类的时候没有写构造器,那么在编译之后也会自动的添加一个无参构造器,这个无参构造器也被称为默认的构造器。

2.1.5 对象的初始化顺序

类加载 概念:将class文件读取加载到JVM内存中的过程,称为类加载
类加载的时机: 1. 创建类的对象 2. 调用类的静态属性或静态方法 3. 执行main方法时,main方法所在的类会被加载 4. 通过反射调用类 Class.forName(“包名.类名”)
类的成员 :属性(实例属性、静态属性);方法(实例方法、静态方法) ;构造方法
代码块 静态代码块:使用static修饰的代码块 注:static关键字可以修饰变量、方法、代码块、匿名类等
初始化顺序 步骤:1. 对象所在的类被加载 执行静态属性和静态代码块(根据定义的顺序,从上往下执行) 特性: 静态变量在类加载时初始化,且在内存中只分配一块空间 静态代码块在类加载时执行,且只执行一次(类只会被加载一次),主要用于初始化静态属 性静态代码块中不能初始化实例变量,只能初始化静态变量 ;2. 对象被创建 执行实例属性和代码块(根据定义的顺序,从上往下执行) 执行构造方法
总结:执行先后顺序: 静态代码块>代码块>构造方法

对象销毁
对象有生命周期,对象生命周期结束时要将分配给该对象的内存地址回收,即对象使用完之后需要对其进行清除。
在创建对象的时候,用户必须使用new操作符为对象分配内存,但是要注意了,在清除对象的时候,由系统自动进行内存回收,不需要用户额外处理,这也是Java语言特色之一,在某种程度上方便了程序员对内存的管理。

  • 当对象引用超过作用范围时将会被视为垃圾
  • 对象被赋值为null将被视为垃圾

内存分析

在JVM的堆区,每个对象都可能处于以下几种状态之一:
1、可触及状态:在一个对象被创建之后,只要程序当中还有引用变量引用它,那么它就始终处于可触及状态;
2、可复活状态:当程序不再有任何引用变量引用该对象时,该对象就进入可复活状态,在这样的状态下,垃圾回收器会准备释放它所占用的内存,在释放之前,会调用它及其他处于可复活状态的对象的finalize()方法,这些finalize()方法有可能使该对象重新转到可触及状态;
3、不可触及状态:当Java虚拟机执行完所有可复活对象的finalize()方法之后,假如,这些方法都没有使该对象转到可触及状态,垃圾回收器才会真正回收它占用的内存。

栈 stack:

  1. 每个线程私有,不能实现线程间的共享!
  2. 局部变量放置于栈中。
  3. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!

堆 heap:

  1. 放置new出来的对象!
  2. 堆是一个不连续的内存空间,分配灵活,速度慢!

方法区(也是堆):

  1. 被所有线程共享!
  2. 用来存放程序中永远是不变或唯一的内容。(类代码信息、静态变量、字符串常量)
    注意:本次内存分析,我们的主要目的是让大家了解基本的内存概念。类加载器、Class对象这些更加详

引用类型的概念

  1. java中,除了基本数据类型之外的其他类型称之为引用类型。
  2. java中的对象是通过引用来操作的。(引用:reference)说白了,引用指的就是对象的地址!

属性(field,或者叫成员变量)

  1. 属性用于定义该类或该类对象包含的数据或者说静态属性。
  2. 属性作用范围是整个类体。
  3. 属性的默认初始化:

2.2 封装

隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。

2.2.1 封装实现

  1. 使用private 修饰需要封装的成员变量。
  2. 提供一个公开的方法设置或者访问私有的属性
    设置 通过set方法,命名格式: set属性名(); 属性的首字母要大写
    访问 通过get方法,命名格式: get属性名(); 属性的首字母要大写

作用和意义

  1. 提高程序的安全性,保护数据。
  2. 隐藏代码的实现细节
  3. 统一用户的调用接口
  4. 提高系统的可维护性
  5. 便于调用者调用。
    良好的封装,便于修改内部代码,提高可维护性。
    良好的封装,可进行数据完整性检测,保证数据的有效性。

2.2.2 方法重载

一个类中包含两个或两个以上同名的方法,其参数不同,称为方法重载(overload)在同一个类中方法名相同 参数列表不同(参数个数、类型、顺序至少有一项不同),即方法签名不同 与方法修饰符、返回值类型、形参名无关

作用:提供同一种功能 的多种实现方式,根据调用者传递的参数来决定采用哪种方式

当Java调用一个重载方法是,参数与调用参数匹配的方法被执行。在使用重载要注意以下的几点:

  1. 在使用重载时只能通过不同的参数列表,必须具有不同的参数列表。
  2. 不能通过访问权限、返回类型、抛出的异常进行重载。
  3. 方法的异常类型和数目不会对重载造成影响。
  4. 可以有不同的返回类型,只要参数列表不同就可以了。
  5. 可以有不同的访问修饰符。
  6. 可以抛出不同的异常。

2.3 继承

extands的意思是“扩展”。子类是父类的扩展。
注意:JAVA中类只有单继承,没有多继承! 接口可以多继承!

  1. 子类拥有父类非 private 的属性和方法。

  2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

  3. 子类可以用自己的方式实现父类的方法。

Super关键字

2.3.1 Object类

java中的每一个类都是"直接" 或者 "间接"的继承了java.lang.Object类

Object类中的getClass()、notify()、notifyAll()、wait()等方法不能被重写,因为这些方法是final类型

getClass()方法
getClass()方法:返回对象执行时的class实例,然后用此实例调用getname()方法获得类的名称

getClass().getname();

toString()方法
toString()方法:将一个对象返回为字符串形式,它会返回一个String实例。
通常重写toString()方法,为对象提供一个特定的输出模式。

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

equals()方法
在java语言中有两种比较对象的方法:“==”\运算符和equals()方法,"=="比较两个对象引用内存地址是否相等,equals()方法比较两根对象的实际内容


public class People {
	int id;// 身份证号
	String name;//名字

	public People(int id, String name) {
		this.id = id;
		this.name = name;
	}

	public boolean equals(Object obj) {// 重写Object的equals()方法
		if (this == obj)// 如果参数与本类是同一个对象
			return true;
		if (obj == null)// 如果参数是null
			return false;
		if (getClass() != obj.getClass())// 如果参数与本类类型不同
			return false;
		People other = (People) obj;// 将参数强转成本类对象
		if (id != other.id)// 如果两者的身份证号不相等
			return false;
		return true;
	}

	public String toString() {// 重写Object的toString()方法
		return  name;//只输出名字
	}

	public static void main(String[] args) {
		People p1 = new People(220, "tom");
		People p2 = new People(220, "汤姆");
		People p3 = new People(330, "张三");
		Object o = new Object();
		
		System.out.println(p1+"与"+p2+"是否为同一人?");
		System.out.println("equals()方法的结果:"+p1.equals(p2));
		System.out.println("==运算符的结果:"+(p1 == p2));
		
		System.out.println();
		System.out.print(p1+"与"+p3+"是否为同一人?");
		System.out.println(p1.equals(p3));
		
		System.out.print(p1+"与"+o+"是否为同一人?");
		System.out.println(p1.equals(o));
	}
}

tom与汤姆是否为同一人?
equals()方法的结果:true
==运算符的结果:false

tom与张三是否为同一人?false
tom与java.lang.Object@2ff4acd0是否为同一人?false

2.3.1 方法重写

在Java程序中,类的继承关系可以产生一个子类,子类继承父类,它具备了父类所有的特征,继承了父类所有的方法和变量。
子类可以定义新的特征,当子类需要修改父类的一些方法进行扩展,增大功能,程序设计者常常把这样的一种操作方法称为重写,也叫称为覆写或覆盖。
重写体现了Java优越性,重写是建立在继承关系上,它使语言结构更加丰富。在Java中的继承中,子类既可以隐藏和访问父类的方法,也可以覆盖继承父类的方法。

在重写方法时,需要遵循以下的规则:

  1. 父类方法的参数列表必须完全与被子类重写的方法的参数列表相同,否则不能称其为重写而是重载。
  2. 父类的返回类型必须与被子类重写的方法返回类型相同,否则不能称其为重写而是重载。静态方法不能重写
  3. Java中规定,被子类重写的方法不能拥有比父类方法更加严格的访问权限。编写过Java程序的人就知道,父类中的方法并不是在任何情况下都可以重写的,当父类中方法的访问权限修饰符为private时,该方法只能被自己的类访问,不能被外部的类访问,在子类是不能被重写的。如果定义父类的方法为public,在子类定义为private,程序运行时就会报错。
  4. 由于父类的访问权限修饰符的限制一定要大于被子类重写方法的访问权限修饰符,而private权限最小。所以如果某一个方法在父类中的访问权限是private,那么就不能在子类中对其进行重写。如果重新定义,也只是定义了一个新的方法,不会达到重写的效果。
  5. 在继承过程中如果父类当中的方法抛出异常,那么在子类中重写父类的该方法时,也要抛出异常,而且抛出的异常不能多于父类中抛出的异常(可以等于父类中抛出的异常)。换句话说,重写方法一定不能抛出新的检查异常,或者比被重写方法声明更加宽泛的检查型异常。

2.4 多态

所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。

多态的优点

  1. 消除类型之间的耦合关系
  2. 可替换性
  3. 可扩充性
  4. 接口性
  5. 灵活性
  6. 简化性

多态存在的三个必要条件

  1. 继承
  2. 重写
  3. 父类引用指向子类对象:Parent p = new Child();

多态的实现

Java实现多态有三个必要条件:继承、重写、向上转型。

继承:在多态中必须存在有继承关系的子类和父类。

重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。

向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。

对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。

对象类型转换
一个对象的实际类型是确定,但是可以指向这个对象的引用的类型,却是可以是这对象实际类型的任意父类型。

class People {
}
class Teacher extends People {
}
public class Demo3 {
	public static void main(String[] args) {
		People tom = new Teacher();//向上转型
	}
}

向下转型要强制转换

instanceof关键字

package test;

class Quadrangle { }

class Square extends Quadrangle { }

class Circular { }

public class Demo5 {
	public static void main(String args[]) {
		Quadrangle q = new Quadrangle(); 	// 四边形对象
		Square s = new Square();			// 正方形对象
		// 判断四边形是否为正方形的子类
		System.out.println(q instanceof Square);
		// 判断正方形是否为四边形的子类
		System.out.println(s instanceof Quadrangle);
		// 由于正方形是否为圆形的子类
		System.out.println(q instanceof Circular);//编译错误
	}
}

false
true

2.5 接口与抽象类

普通类:只有具体实现
抽象类:具体实现和规范(抽象方法) 都有!
接口:只有规范!

2.5.1 抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。

父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。

在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。

在 Java 语言中使用 abstract class 来定义抽象类。

在这里插入代码片

抽象类总结规定

  1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

  4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

2.5.2 接口

接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

[可见度] interface 接口名称 [extends 其他的接口名] {
        // 声明变量
        // 抽象方法
}

声明接口的关键字是interface
接口是用来被类实现的,java中的接口可以被多实现。
一个接口的引用,可以指向这个接口的任意实现类对象
实现的关键字是implements

...implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...

interface Paintable { // 可绘制接口
	public void draw(); // 绘制抽象方法
}

class Quadrangle { // 四边形类
	public void doAnything() {
		System.out.println("四边形提供的方法");
	}
}

//平行四边形类,继承四边形类,并实现了可绘制接口
class Parallelogram extends Quadrangle implements Paintable {
	public void draw() { // 由于该类实现了接口,所以需要覆盖draw()方法
		System.out.println("绘制平行四边形");
	}
}

//正方形类,继承四边形类,并实现了可绘制接口
class Square extends Quadrangle implements Paintable {
	public void draw() {
		System.out.println("绘制正方形");
	}
}


//圆形类,仅实现了可绘制接口
class Circular implements Paintable {
	public void draw() {
		System.out.println("绘制圆形");
	}
}

public class Demo7 {
	public static void main(String[] args) {
		Square s = new Square();
		s.draw();
		s.doAnything();

		Parallelogram p = new Parallelogram();
		p.draw();
		p.doAnything();

		Circular c = new Circular();
		c.draw();
	}
}

绘制正方形
四边形提供的方法
绘制平行四边形
四边形提供的方法
绘制圆形

2.5.3 接口和抽象类的比较

抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。

从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。

相同点

接口和抽象类都不能实例化
都位于继承的顶端,用于被其他实现或继承
都包含抽象方法,其子类都必须覆写这些抽象方法
不同点
|参数|抽象类|接口|
|–|–|–|–
|声明|抽象类使用abstract关键字声明|接口使用interface关键字声明
实现|子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现|子类使用implements关键字来实现接口。它需要提供接口中所有声明的方法的实现
|构造器|抽象可以有构造器|接口不能有构造器
访问修饰符|抽象类中的方法可以是任意访问修饰符|接口方法默认修饰符是public。并且不允许定义为private或者protected
多继承|个类最多只能继承一个抽象类|个类可以实现多个接口
字段声明|抽象类的字段声明可以是任意的|接口的字段默认都是static和final的

3 异常处理

异常发生的原因有很多,通常包含以下几大类:
用户输入了非法数据。
要打开的文件不存在。
网络通信时连接中断,或者JVM内存溢出。

3.1 异常

常见三种类型的异常:
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。n

Java把异常当作对象来处理,并定义一个基类 java.lang.Throwable 作为所有异常的超类。
在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
Error表示不希望被程序捕获或者是程序无法处理的错误。另一个分支是Exception表示用户程序可能捕捉的异常情况或者说是程序可以处理的异常。

Java 的非检查性异常

异常 描述
ArithmeticException 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。
ArrayIndexOutOfBoundsException 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
ArrayStoreException 试图将错误类型的对象存储到一个对象数组时抛出的异常。
ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常。
IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。
IllegalMonitorStateException 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。
IllegalStateException 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。
IllegalThreadStateException 线程没有处于请求操作所要求的适当状态时抛出的异常。
IndexOutOfBoundsException 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
NegativeArraySizeException 如果应用程序试图创建大小为负的数组,则抛出该异常。
NullPointerException 当应用程序试图在需要对象的地方使用 null 时,抛出该异常
NumberFormatException 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
SecurityException 由安全管理器抛出的异常,指示存在安全侵犯。
StringIndexOutOfBoundsException 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
UnsupportedOperationException 当不支持请求的操作时,抛出该异常。

Java 定义在 java.lang 包中的检查性异常类

异常 描述
ClassNotFoundException 应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
IllegalAccessException 拒绝访问一个类的时候,抛出该异常。
InstantiationException 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。
InterruptedException 一个线程被另一个线程中断,抛出该异常。
NoSuchFieldException 请求的变量不存在
NoSuchMethodException 请求的方法不存在

自定义异常
1、创建自定义异常类
2、在方法中通过throw关键字抛出异常
3、如果在当前抛出异常的方法中处理异常,可以使用try-catch语句块捕获并处理,否则在声明出通过throw关键字指明要抛出给方法调用者的异常,继续下一步动作
4、在出现异常的方法中捕获并处理异常

public class MyException extends Exception {	//创建自定义异常,继承Exception类
	public MyException(String ErrorMessage) { 	//构造方法
		super(ErrorMessage); 				//父类构造方法
	}
}

public class Tran { // 创建类
	static int avg(int number1, int number2) throws MyException { // 定义方法,抛出异常
		if (number1 < 0 || number2 < 0) { // 判断方法中参数是否满足指定条件
			throw new MyException("不可以使用负数"); // 错误信息
		}
		if (number1 > 100 || number2 > 100) { // 判断方法中参数是否满足指定条件
			throw new MyException("数值太大了"); // 错误信息
		}
		return (number1 + number2) / 2; // 将参数的平均值返回
	}

	public static void main(String[] args) { // 主方法
		try { // try代码块处理可能出现异常的代码
			int result = avg(102, 150); // 调用avg()方法
			System.out.println(result); // 将avg()方法的返回值输出
		} catch (MyException e) {
			System.out.println(e); // 输出异常信息
		}
	}
}

3.2 异常处理机制

异常处理五个关键字
分别是: try 、 catch 、 finally 、 throw 、 throws
try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常
时,异常就被抛出。
catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。
finally – finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络
连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语
句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
throw – 用于抛出异常。
throws – 用在方法签名中,用于声明该方法可能抛出的异常。

3.2.1 异常抛出

使用throw关键字抛出异常

try{
//code that might generate exceptions
}catch(Exception e){
//the code of handling exception1
}catch(Exception e){
//the code of handling exception2
}

关键词 try 后的一对大括号将一块可能发生异常的代码包起来,即为监控区域。Java方法在运行过程中发生了异常,则创建异常对象。

3.2.2 处理异常

对于 运行时异常 、 错误 和 检查异常 ,Java技术所要求的异常处理方式有所不同
由于运行时异常及其子类的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将
由Java运行时系统自动抛出,允许应用程序忽略运行时异常。
对于方法运行中可能出现的 Error ,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因
为,大多数 Error 异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。

4 常用类库

4.1 包装类

为了能将数据类型视为对象进行处理,提出了包装类概念,将基本数据类型封装到包装类中

基本数据类型对应的包装类
byteByte
shortShort
intInteger
longLong
charCharacter
floatFloat
doubleDouble
booleanBoolean

Integer类的常用方法


public class IntegerDemo {
	public static void main(String[] args) {
		int num = Integer.parseInt("456"); // 将字符串转换为int类型
		Integer iNum = Integer.valueOf("456"); // 通过构造函数创建一个Integer对象
		System.out.println("int数据与Integer对象的比较:" + iNum.equals(num));
		String str2 = Integer.toBinaryString(num); // 获取数字的二进制表示
		String str3 = Integer.toHexString(num); // 获取数字的十六进制表示
		String str4 = Integer.toOctalString(num); // 获取数字的八进制表示
		String str5 = Integer.toString(num, 15); // 获取数字的十五进制表示
		System.out.println("456的二进制表示为:" + str2);
		System.out.println("456的十六进制表示为:" + str3);
		System.out.println("456的八进制表示为:" + str4);
		System.out.println("456的十五进制表示为:" + str5);
	}
}

int数据与Integer对象的比较:true
456的二进制表示为:111001000
456的十六进制表示为:1c8
456的八进制表示为:710
456的十五进制表示为:206

上面的例子都需要手动实例化一个包装类,称为手动拆箱装箱。Java 1.5(5.0) 之前必须手动拆箱装箱。
Java 1.5 之后可以自动拆箱装箱,也就是在进行基本数据类型和对应的包装类转换时,系统将自动进
行,这将大大方便程序员的代码书写。

public static void main(String[] args) {
	int m = 500;
	Integer obj = m; // 自动装箱
	int n = obj; // 自动拆箱
	System.out.println("n = " + n);
	Integer obj1 = 500;
	System.out.println("obj 等价于 obj1?" + obj.equals(obj1));
}

4.2 String

4.2.1 String

字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。
String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。 字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享

//String的成员变量

//String的属性值
private final char value[];
//数组被使用的开始位置
private final int offset;
//String中元素的个数
private final int count;
//String类型的hash值
private int hash; // Default to 0

private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
//String的构造方法

String()
//初始化一个新创建的 String 对象,使其表示一个空字符序列。
String(byte[] bytes)
//通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
String(byte[] bytes, Charset charset)
//通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
String(byte[] bytes, int offset, int length)
//通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
String(byte[] bytes, int offset, int length, Charset charset)
//通过使用指定的 charset 解码指定的 byte 子数组,构造一个新的 String。
String(byte[] bytes, int offset, int length, String charsetName)
//通过使用指定的字符集解码指定的 byte 子数组,构造一个新的 String。
String(byte[] bytes, String charsetName)
//通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
String(char[] value)
//分配一个新的 String,使其表示字符数组参数中当前包含的字符序列。
String(char[] value, int offset, int count)
//分配一个新的 String,它包含取自字符数组参数一个子数组的字符。
String(int[] codePoints, int offset, int count)
//分配一个新的 String,它包含 Unicode 代码点数组参数一个子数组的字符。
String(String original)
//初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建
的字符串是该参数字符串的副本。
String(StringBuffer buffer)
//分配一个新的字符串,它包含字符串缓冲区参数中当前包含的字符序列。
String(StringBuilder builder)
//分配一个新的字符串,它包含字符串生成器参数中当前包含的字符序列。

创建字符串
String 直接赋值创建的字符串存储在在方法区的常量池中,而 new 创建的字符串对象在堆上

String s1 = "Runoob";              // String 直接创建
String s2 = "Runoob";              // String 直接创建
String s3 = s1;                    // 相同引用
String s4 = new String("Runoob");   // String 对象创建
String s5 = new String("Runoob");   // String 对象创建

获取字符串信息

字符串连接

public class StringDemo {
	public static void main(String arg[]) {
		String s1="hello";
		String s2 = new String("world");
		String s3 = s1 + "\n" +s2;//s1,\n,s2连接
		int size = s3.length();//字符串长度
		int n1 = s3.indexOf("l");//返回"l"第一次出现的索引位置
		int n2 = s3.lastIndexOf("l");//返回"l"最后一次出现的索引位置
		char c1 = s3.charAt(4);//返回指定索引处的字符

		System.out.println(s3);
		System.out.println(size);
		System.out.println(n1);
		System.out.println(n2);
		System.out.println(c1);
		
	}
}

4.2.2 字符串操作

String的判断

boolean equals(Object obj):比较字符串的内容是否相同
boolean equalsIgnoreCase(String str): 比较字符串的内容是否相同,忽略大小写
boolean startsWith(String str): 判断字符串对象是否以指定的str开头
boolean endsWith(String str): 判断字符串对象是否以指定的str结尾

字符串截取

int length():获取字符串的长度,其实也就是字符个数
char charAt(int index):获取指定索引处的字符
int indexOf(String str):获取str在字符串对象中第一次出现的索引
String substring(int start):从start开始截取字符串
String substring(int start,int end):从start开始,到end结束截取字符串。包括start,
不包括end

String转换

char[] toCharArray():把字符串转换为字符数组
String toLowerCase():把字符串转换为小写字符串
String toUpperCase():把字符串转换为大写字符串

其它

去除字符串两端空格:String trim()
按照指定符号分割字符串:String[] split(String str)

4.2.3 StringBuffer 和 StringBuilder

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。

public class RunoobTest{
    public static void main(String args[]){
        StringBuilder sb = new StringBuilder(10);
        sb.append("Runoob..");
        System.out.println(sb);  
        sb.append("!");
        System.out.println(sb); 
        sb.insert(8, "Java");
        System.out.println(sb); 
        sb.delete(5,8);
        System.out.println(sb);  
    }
}
public class Test{
  public static void main(String args[]){
    StringBuffer sBuffer = new StringBuffer("菜鸟教程官网:");
    sBuffer.append("www");
    sBuffer.append(".runoob");
    sBuffer.append(".com");
    System.out.println(sBuffer);  
  }
}

4.3 数字处理

4.3.1 数字格式化-DecimalFormat类


import java.text.DecimalFormat;

public class DecimalFormatSimpleDemo {
	// 使用实例化对象时设置格式化模式
	static public void SimgleFormat(String pattern, double value) {
		DecimalFormat myFormat = new DecimalFormat(pattern); // 实例化DecimalFormat对象
		String output = myFormat.format(value); // 将数字进行格式化
		System.out.println(value + " " + pattern + " " + output);
	}

	// 使用applyPattern()方法对数字进行格式化
	static public void UseApplyPatternMethodFormat(String pattern, double value) {
		DecimalFormat myFormat = new DecimalFormat(); // 实例化DecimalFormat对象
		myFormat.applyPattern(pattern); // 调用applyPattern()方法设置格式化模板
		System.out.println(value + " " + pattern + " " + myFormat.format(value));
	}

	public static void main(String[] args) {
		SimgleFormat("###,###.###", 123456.789); // 调用静态SimgleFormat()方法
		SimgleFormat("00000000.###kg", 123456.789); // 在数字后加上单位
		// 按照格式模板格式化数字,不存在的位以0显示
		SimgleFormat("000000.000", 123.78);
		// 调用静态UseApplyPatternMethodFormat()方法
		UseApplyPatternMethodFormat("#.###%", 0.789); // 将数字转换为百分数形式
		UseApplyPatternMethodFormat("###.##", 123456.789); // 将小数点后格式化为两位
		UseApplyPatternMethodFormat("0.00\u2030", 0.789); // 将数字转化为千分数形式
	}
}

4.3.2 数学函数-Math类

package test;

public class MathDemo {

	public static void main(String arg[]) {
		/**
		*Math.sqrt()//计算平方根
		*Math.cbrt()//计算立方根
		*Math.pow(a, b)//计算a的b次方
		*Math.max( , );//计算最大值
		*Math.min( , );//计算最小值
		*/
		System.out.println(Math.sqrt(16)); //4.0
		System.out.println(Math.cbrt(8)); //2.0
		System.out.println(Math.pow(3,2)); //9.0
		System.out.println(Math.max(2.3,4.5));//4.5
		System.out.println(Math.min(2.3,4.5));//2.3
		/**
		* abs求绝对值
		*/
		System.out.println(Math.abs(-10.4)); //10.4
		System.out.println(Math.abs(10.1)); //10.1
		/**
		* ceil天花板的意思,就是返回大的值
		*/
		System.out.println(Math.ceil(-10.1)); //-10.0
		System.out.println(Math.ceil(10.7)); //11.0
		System.out.println(Math.ceil(-0.7)); //-0.0
		System.out.println(Math.ceil(0.0)); //0.0
		System.out.println(Math.ceil(-0.0)); //-0.0
		System.out.println(Math.ceil(-1.7)); //-1.0
		/**
		* floor地板的意思,就是返回小的值
		*/
		System.out.println(Math.floor(-10.1)); //-11.0
		System.out.println(Math.floor(10.7)); //10.0
		System.out.println(Math.floor(-0.7)); //-1.0
		System.out.println(Math.floor(0.0)); //0.0
		System.out.println(Math.floor(-0.0)); //-0.0
		/**
		* random 取得一个大于或者等于0.0小于不等于1.0的随机数 [0,1)
		*/
		System.out.println(Math.random()); //小于1大于0的double类型的数
		System.out.println(Math.random()+1);//大于1小于2的double类型的数
		/**
		* rint 四舍五入,返回double值
		* 注意.5的时候会取偶数 异常的尴尬=。=
		*/
		System.out.println(Math.rint(10.1)); //10.0
		System.out.println(Math.rint(10.7)); //11.0
		System.out.println(Math.rint(11.5)); //12.0
		System.out.println(Math.rint(10.5)); //10.0
		System.out.println(Math.rint(10.51)); //11.0
		System.out.println(Math.rint(-10.5)); //-10.0
		/**
		*Math.sqrt()//计算平方根
		*Math.cbrt()//计算立方根
		*Math.pow(a, b)//计算a的b次方
		*Math.max( , );//计算最大值
		*Math.min( , );//计算最小值
		*/
		System.out.println(Math.sqrt(16)); //4.0
		System.out.println(Math.cbrt(8)); //2.0
		System.out.println(Math.pow(3,2)); //9.0
		System.out.println(Math.max(2.3,4.5));//4.5
		System.out.println(Math.min(2.3,4.5));//2.3
		/**
		* abs求绝对值
		*/
		System.out.println(Math.abs(-10.4)); //10.4
		System.out.println(Math.abs(10.1)); //10.1
		/**
		* ceil天花板的意思,就是返回大的值
		*/
		System.out.println(Math.ceil(-10.1)); //-10.0
		System.out.println(Math.ceil(10.7)); //11.0
		System.out.println(Math.ceil(-0.7)); //-0.0
		System.out.println(Math.ceil(0.0)); //0.0
		System.out.println(Math.ceil(-0.0)); //-0.0
		System.out.println(Math.ceil(-1.7)); //-1.0
		/**
		* floor地板的意思,就是返回小的值
		*/
		System.out.println(Math.floor(-10.1)); //-11.0
		System.out.println(Math.floor(10.7)); //10.0
		System.out.println(Math.floor(-0.7)); //-1.0
		System.out.println(Math.floor(0.0)); //0.0
		System.out.println(Math.floor(-0.0)); //-0.0
		/**
		* random 取得一个大于或者等于0.0小于不等于1.0的随机数 [0,1)
		*/
		System.out.println(Math.random()); //小于1大于0的double类型的数
		System.out.println(Math.random()+1);//大于1小于2的double类型的数
		/**
		* rint 四舍五入,返回double值
		* 注意.5的时候会取偶数 异常的尴尬=。=
		*/
		System.out.println(Math.rint(10.1)); //10.0
		System.out.println(Math.rint(10.7)); //11.0
		System.out.println(Math.rint(11.5)); //12.0
		System.out.println(Math.rint(10.5)); //10.0
		System.out.println(Math.rint(10.51)); //11.0
		System.out.println(Math.rint(-10.5)); //-10.0
	}
	
}

4.3.1 随机数生成器-Random类

package test;

import java.util.Random;

public class RandDemo {
	public static void main(String[] args) {
		Random r = new Random(); // 实例化一个Random类
		// 随机产生一个整数
		System.out.println("随机产生一个整数:" + r.nextInt());
		// 随机产生一个大于等于0且小于10的整数
		System.out.println("随机产生一个大于等于0小于10的整数:" + r.nextInt(10));
		// 随机产生一个布尔型的值
		System.out.println("随机产生一个布尔型的值:" + r.nextBoolean());
		// 随机产生一个双精度型的值
		System.out.println("随机产生一个双精度型的值:" + r.nextDouble());
		// 随机产生一个浮点型的值
		System.out.println("随机产生一个浮点型的值:" + r.nextFloat());
		// 随机产生一个概率密度为高斯分布的双精度值
		System.out.println("随机产生一个概率密度为高斯分布的双精度值:" + r.nextGaussian());
	}
}

4.3.1 大数运算-BigDecimal类和BigInteger类


import java.math.BigInteger;

public class BigIntegerDemo {
	public static void main(String[] args) {
		BigInteger b1= new BigInteger("987654321987654321"); // 第1个大数字
		BigInteger b2 = new BigInteger("123456789123456789"); // 第2个大数字
		// 加法运算
		System.out.println("加法操作:" + b1.add(b2));
		// 减法运算
		System.out.println("减法操作:" + b1.subtract(b2));
		// 乘法运算
		System.out.println("乘法操作:" + b1.multiply(b2));
		// 除法运算
		System.out.println("除法操作:" + b1.divide(b2));
		// 取商运算
		System.out.println("取商:" + b1.divideAndRemainder(b2)[0]);
		// 取余运算
		System.out.println("取余数:" + b1.divideAndRemainder(b2)[1]);
		// 2次方运算
		System.out.println("做2次方操作:" + b1.pow(2));
		// 相反数运算
		System.out.println("取相反数操作:" + b1.negate());
	}
}

package test;

import java.math.BigDecimal;
import java.math.RoundingMode;


public class BigDecimal{
	public static void main(String[] args) {
		BigDecimal b1= new BigDecimal("0.987654321987654321"); // 第1个大数字
		BigDecimal b2 = new BigDecimal("0.123456789123456789"); // 第2个大数字
		// 加法运算
		System.out.println("加法操作:" + b1.add(b2));
		// 减法运算
		System.out.println("减法操作:" + b1.subtract(b2));
		// 乘法运算
		System.out.println("乘法操作:" + b1.multiply(b2));
		// 除法运算
		System.out.println("除法操作,保留小数点后9位,并四舍五入:" + b1.divide(b2,9,RoundingMode.HALF_UP));
	}
}


4.4 时间日期

4.4.1 Date类

构造方法

构造方法说明
Date()使用当前日期和时间来初始化对象
Date(long millisec)数接收一个参数,该参数是从1970年1月1日起的毫秒数。

常用方法

方法说明
boolean after(Date date)若当调用此方法的Date对象在指定日期之后返回true,否则返回false。
boolean before(Date date)若当调用此方法的Date对象在指定日期之前返回true,否则返回false。
Object clone( )返回此对象的副本。
int compareTo(Date date)比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数。
int compareTo(Object obj)若obj是Date类型则操作等同于compareTo(Date) 。否则它抛出ClassCastException。
boolean equals(Object date)当调用此方法的Date对象和指定日期相等时候返回true,否则返回false。
long getTime( )返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
int hashCode( )返回此对象的哈希码值。
void setTime(long time)用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期。
String toString( )把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。

4.4.2 SimpleDateFormat类格式化日期

SimpleDateFormat 是一个以语言环境敏感的方式来格式化和分析日期的类。SimpleDateFormat 允许
你选择任何用户自定义日期时间格式来运行。例如:

public static void main(String args[]) {
Date dNow = new Date( );
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
System.out.println("当前时间为: " + ft.format(dNow));
}

其中 yyyy 是完整的公元年,MM 是月份,dd 是日期,HH:mm:ss 是时、分、秒。
注意:有的格式大写,有的格式小写,例如 MM 是月份,mm 是分;HH 是 24 小时制,而 hh 是 12 小时制。

4.4.3 Calendar类

Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可。


import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class CountDown {
	public static void main(String[] args) {
		System.out.println("——————————共和国建立100周年倒计时——————————");
		Date date = new Date(); // 当前时间
		// 创建SimpleDateFormat对象,指定目标格式
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
		// 调用format方法,格式化时间,转换为指定方法
		String today = simpleDateFormat.format(date);
		System.out.println("今天是" + today); // 输出当前日期
		// 获取自1970年1月1日至当前时间所经过的毫秒数
		long time1 = date.getTime();
		// 使用默认时区和语言环境获得一个日历calendar
		Calendar calendar = Calendar.getInstance();
		// 设置日历calendar中的 年、月 和日的值。因为月份是从0开始计算的,所以这里要减一
		calendar.set(2049, 10 - 1, 1);
		// 计算自1970年1月1日至2049年10月1日所经过的毫秒数
		long time2 = calendar.getTimeInMillis();
		// 计算2049年10月1日距离当前时间相差的天数
		long day = (time2 - time1) / (1000 * 60 * 60 * 24);
		System.out.println("距离2049年10月1日还有 " + day + " 天!");
	}
}

4.4.4 Runtime类

提供JDK对运行时间

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class RuntimeExecDemo {
	public static void main(String[] args) {
		Runtime r = Runtime.getRuntime(); // 获取本地Runtime对象
		try {
			Process p = r.exec("help"); // 执行help命令,获取进程对象
			InputStream is = p.getInputStream(); // 获取进程的字节输入流
			// 将字节输入流转化为字符输入流
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String str = null; // 创建null字符串
			while ((str = br.readLine()) != null) { // 如果字符流中可以获取非空内容
				System.out.println(str); // 打印获取的内容
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

public class MemoryDemo {
	public static void main(String[] args) {
		Runtime r = Runtime.getRuntime(); // 获取本地Runtime对象
		Integer ints[] = new Integer[10000]; // 创建长度为一万的整型数组
		long before = r.freeMemory(); // 获取当前空闲内存数
		System.out.println("赋值前空闲内存字节数:" + before);
		// 循环为整型数组赋值
		for (int i = 0, length = ints.length; i < length; i++) {
			ints[i] = i;// 赋值
		}
		long after = r.freeMemory(); // 获取当前空闲内存数
		System.out.println("赋值后空闲内存字节数:" + after);
		// 输出数组用掉的内存量
		System.out.println("数组用掉的内存字节数:" + (before - after));
	}
}

4.5 输入输出

public class SystemTimeDemo {
	public static void main(String[] args) {
		long start = System.currentTimeMillis(); // 程序开始记录时间
		String str = null; // 创建null字符串
		for (int i = 0; i < 10000; i++) { // 循环一万次
			str += i; // 字符串与循环变量拼接
		}
		long end = System.currentTimeMillis(); // 记录循环结束时间
		System.out.println("循环用时:" + (end - start) + "毫秒");
	}
}


import java.util.Random;
import java.util.Scanner;

public class ScannerDemo {

	public static void main(String[] args) {
		Random r = new Random();// 随机数对象
		int num = r.nextInt(100);// 从1~99取值
		int input = -1;// 记录用户输入的值
		Scanner sc = new Scanner(System.in);// 扫描器扫描控制台输入
		while (true) {
			System.out.println("猜一猜随机数是多少?");
			input = sc.nextInt();// 获取用户输入的一个整数
			if (input > num) {// 如果大于随机数
				System.out.print("你输入的数字大了! ");
			} else if (input < num) {// 如果小于随机数
				System.out.print("你输入的数字小了! ");
			} else if (input == num) {// 如果等于随机数
				break;// 结束循环
			} else {
				System.out.println("您的输入有误! ");
			}
		}
		System.out.println("恭喜你答对了!");
		sc.close();// 关闭扫描器
	}
}

4.6 枚举和泛型

4.6.1 枚举

java语言中由关键字enum来定义一个枚举类型。枚举的特点是有限且固定的类,枚举类是再JDK1.5版本中才引入的,存放在java.lang包中。

常量放在接口中可以直接使用,修饰符为fina和static

public interface Constans{
	public static fina int Countans_A = 1;
	public static fina int Countans_B = 2;
}

枚举定义常量取代上述常量定义方式

public enum Countans{
	Countans_A;
	Countans_B;
}

interface SeasonInterface {							// 四季接口
	int SPRING = 1, SUMMER = 2, AUTUMN = 3, WINTER = 4;
}

enum SeasonEnum {								// 四季枚举
	SPRING, SUMMER, AUTUMN, WINTER
}

public class SeasonDemo {

	public static void printSeason1(int season) {
		switch (season) {
		case SeasonInterface.SPRING:
			System.out.println("这是春季");break;
		case SeasonInterface.SUMMER:
			System.out.println("这是夏季");break;
		case SeasonInterface.AUTUMN:
			System.out.println("这是秋季");break;
		case SeasonInterface.WINTER:
			System.out.println("这是冬季");break;
		default:
			System.out.println("这不是四季的常量值");
		}
	}
	
	public static void printSeason2(SeasonEnum season) {
		switch (season) {
		case SPRING:
			System.out.println("这是春季");break;
		case SUMMER:
			System.out.println("这是夏季");break;
		case AUTUMN:
			System.out.println("这是秋季");break;
		case WINTER:
			System.out.println("这是冬季");break;
		}
	}

	public static void main(String[] args) {
		printSeason1(SeasonInterface.SPRING);	// 使用接口常量做参数
		printSeason1(3);						// 可以使用数字做出参数
		printSeason1(-1);					// 也使用接口常量值以外的数字“冒充”常量
		printSeason2(SeasonEnum.WINTER); 	// 使用枚举做参数,只能用枚举有中的值,无法“冒充”
	}
}

枚举类型常用方法含义举例
values()数组形式返回枚举类型成员Countans.values()
valueOf()将普通字符转换为枚举实例
compareTo()比较两个枚举对象在定义时的顺序
ordinal()得到枚举成员的位置索引
package test;


enum SeasonEnum { // 四季枚举
	SPRING, SUMMER, AUTUMN, WINTER
}

public class ShowEnum {
	public static void main(String[] args) {
		SeasonEnum es[] = SeasonEnum.values();
		for (int i = 0; i < es.length; i++) {
			System.out.println("枚举常量:" + es[i]);
		}
	}
}

4.6.2 泛型

java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
如何解决以下强制类型转换时容易出现的异常问题?
List的get(int index)方法获取元素
Map的get(Object key)方法获取元素
Iterator的next()方法获取元素

? 通配符: < ? >

java 中泛型标记符:
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的 java 类型

public class Book<T> {								// 定义带泛型的Book<T>类
	private T bookInfo;								// 类型形参:书籍信息
	public Book(T bookInfo) {							// 参数为类型形参的构造方法
		this.bookInfo = bookInfo;						// 为书籍信息赋值
	}
	public T getBookInfo() {							// 获取书籍信息的值
		return bookInfo;
	}
	public static void main(String[] args) {
		// 创建参数为String类型的书名对象
		Book<String> bookName = new Book<String>("《Java从入门到精通》");
		// 创建参数为String类型的作者对象
		Book<String> bookAuthor = new Book<String>("明日科技");
		// 创建参数为Double类型的价格对象
		Book<Double> bookPrice = new Book<Double>(69.8);
		// 创建参数为Boolean类型的附赠源码
		Book<Boolean> hasSource = new Book<Boolean>(true);
		// 控制台输出书名、作者、价格和是否附赠光盘
		System.out.println("书名:" + bookName.getBookInfo());
		System.out.println("作者:" + bookAuthor.getBookInfo());
		System.out.println("价格:" + bookPrice.getBookInfo());
		System.out.println("是否附赠源码?" + hasSource.getBookInfo());
	}
}

5 集合

集合框架被设计成要满足以下几个目标。
1、该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
2、该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
3、对一个集合的扩展和适应必须是简单的。
为此,整个集合框架就围绕一组标准接口而设计。你可以直接使用这些接口的标准实现,诸如: LinkedList, HashSet, 和 TreeSet 等,除此之外你也可以通过这些接口实现自己的集合。

Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。

集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:

接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象

实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。

算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

Collection 接口存储一组不唯一,无序的对象 List 接口存储一组不唯一,有序的对象。 Set 接口存储一组唯一,无序的对象
Map 接口存储一组键值对象,提供key到value的映射
ArrayList实现了长度可变的数组,在内存中分配连续的空间。遍历元素和随机访问元素的效率比较 高

5.1 Collection接口

5.2 List集合

List集合List接口及List接口的所有实现类。List集合中元素允许重复,各元素的顺序是对象插入的循序。

List接口继承了Collection接口,包含Collection接口所有方法外还定义了两个重要方法:

get(int index):获取指定索引位置的元素
set(int index,Object obj):将集合中指定索引位置的对象修改为指定对象

List接口实现类
1、ArrayList:实现可变数组,允许保存所有元素包括nul,可以快速随机访问
1、LinkedList:类似链表,插入删除效率更高

5.2.1 ArrayList

import java.util.ArrayList;
import java.util.List;

public class Gather { 							//创建类Gather
	public static void main(String[] args) { 			//主方法
		List<String> list = new ArrayList<>(); 		//创建集合对象
		list.add("a"); 							//向集合添加元素
		list.add("b");
		list.add("c");
		int i = (int) (Math.random()*list.size());		//获得0~2之间的随机数
		System.out.println("随机获取集合中的元素:" + list.get(i));
		list.remove(2); 							//将指定索引位置的元素从集合中移除
		System.out.println("将索引是'2'的元素从集合移除后,集合中的元素是:");
		for (int j = 0; j < list.size(); j++) { 			//循环遍历集合
			System.out.println(list.get(j));
		}
	}
}

1、arrayList可以存放null。
2、arrayList本质上就是一个elementData数组。
3、arrayList区别于数组的地方在于能够自动扩展大小,其中关键的方法就是gorw()方法。
4、arrayList中removeAll(collection c)和clear()的区别就是removeAll可以删除批量指定的元素,而clear是全是删除集合中的元素。
5、arrayList由于本质是数组,所以它在数据的查询方面会很快,而在插入删除这些方面,性能下降很多,有移动很多数据才能达到应有的效果
6、arrayList实现了RandomAccess,所以在遍历它的时候推荐使用for循环。

常用方法:
add() 将元素插入到指定位置的 arraylist 中
addAll() 添加集合中的所有元素到 arraylist 中
clear() 删除 arraylist 中的所有元素
clone() 复制一份 arraylist
contains() 判断元素是否在 arraylist
get() 通过索引值获取 arraylist 中的元素
indexOf() 返回 arraylist 中元素的索引值
removeAll() 删除存在于指定集合中的 arraylist 里的所有元素
remove() 删除 arraylist 里的单个元素
size() 返回 arraylist 里元素数量
isEmpty() 判断 arraylist 是否为空
subList() 截取部分 arraylist 的元素
set() 替换 arraylist 中指定索引的元素
sort() 对 arraylist 元素进行排序
toArray() 将 arraylist 转换为数组
toString() 将 arraylist 转换为字符串
ensureCapacity() 设置指定容量大小的 arraylist
lastIndexOf() 返回指定元素在 arraylist 中最后一次出现的位置
retainAll() 保留 arraylist 中在指定集合中也存在的那些元素
containsAll() 查看 arraylist 是否包含指定集合中的所有元素
trimToSize() 将 arraylist 中的容量调整为数组中的元素个数
removeRange() 删除 arraylist 中指定索引之间存在的元素
replaceAll() 将给定的操作内容替换掉数组中每一个元素
removeIf() 删除所有满足特定条件的 arraylist 元素
forEach() 遍历 arraylist 中每一个元素并执行特定操作

5.2.2 LinkedList

LinkedList 继承了 AbstractSequentialList 类。
LinkedList 实现了 Queue 接口,可作为队列使用。
LinkedList 实现了 List 接口,可进行列表的相关操作。
LinkedList 实现了 Deque 接口,可作为队列使用。
LinkedList 实现了 Cloneable 接口,可实现克隆。
LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输。

常用方法:
public boolean add(E e) 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。
public void add(int index, E element) 向指定位置插入元素。
public boolean addAll(Collection c) 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。
public boolean addAll(int index, Collection c) 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。
public void addFirst(E e) 元素添加到头部。
public void addLast(E e) 元素添加到尾部。
public boolean offer(E e) 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。
public boolean offerFirst(E e) 头部插入元素,返回是否成功,成功为 true,失败为 false。
public boolean offerLast(E e) 尾部插入元素,返回是否成功,成功为 true,失败为 false。
public void clear() 清空链表。
public E removeFirst() 删除并返回第一个元素。
public E removeLast() 删除并返回最后一个元素。
public boolean remove(Object o) 删除某一元素,返回是否成功,成功为 true,失败为 false。
public E remove(int index) 删除指定位置的元素。
public E poll() 删除并返回第一个元素。
public E remove() 删除并返回第一个元素。
public boolean contains(Object o) 判断是否含有某一元素。
public E get(int index) 返回指定位置的元素。
public E getFirst() 返回第一个元素。
public E getLast() 返回最后一个元素。
public int indexOf(Object o) 查找指定元素从前往后第一次出现的索引。
public int lastIndexOf(Object o) 查找指定元素最后一次出现的索引。
public E peek() 返回第一个元素。
public E element() 返回第一个元素。
public E peekFirst() 返回头部元素。
public E peekLast() 返回尾部元素。
public E set(int index, E element) 设置指定位置的元素。
public Object clone() 克隆该列表。
public Iterator descendingIterator() 返回倒序迭代器。
public int size() 返回链表元素个数。
public ListIterator listIterator(int index) 返回从指定位置开始到末尾的迭代器。
public Object[] toArray() 返回一个由链表元素组成的数组。
public T[] toArray(T[] a) 返回一个由链表元素转换类型而成的数组。

5.3 Set集合

Set集合继承Collection接口,其中的对象不按特定的方式排序,不包括重复对象

Set接口常用实现类:
1、HashSet类:哈希表支持,不保证顺序不变
2、TreeSet类:递增排序

5.4 Map集合

Map集合没有继承Collection接口,提供key-value映射,散列存储。Map中不包含相同的key,每个key只能映射一个value。

Map接口常用实现类:
1、HashMap类:哈希表支持,不保证顺序不变
2、TreeMap类:映射关系有一定顺序

import java.util.HashMap;

public class RunoobTest {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");
        System.out.println(Sites);
    }
}

6 lambda表达式和流处理

7 I/O

在Java程序中,对于数据的输入/输出操作以“流”(Stream)方式进行;JDK提供了各种各样的“流”类,用以获取不同种类的数据:程序中通过标准的方法输入或输出数据。

流是用来读写数据的,java有一个类叫File,它封装的是文件的文件名,只是内存里面的一个对象,真正的文件是在硬盘上的一块空间,在这个文件里面存放着各种各样的数据,我们想读文件里面的数据怎么办呢?是通过一个流的方式来读,咱们要想从程序读数据,对于计算机来说,无论读什么类型的数据都是以010101101010这样的形式读取的。

8 注解与反射

9 多线程

10 网络通信

11 JVM

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤影墨客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值