JavaSE:标准版(桌面程序、控制台开发…)
JavaME:嵌入式开发(手机、小家电…)
JavaEE:E企业开发(web端、服务器开发)
JDK:Java Development Kit
JRE:Java Runtime Environment
JVM:Java Virtual Machine
删除Java的安装目录
删除JAVA_HOME
删除path下关于java的目录
cmd查询java -version
java -version1.随便新建一个文件夹,存放代码
2.新建一个java文件
文件后缀名为.java。即Hello.java
public class Hello{
public static void main(String[] args){
System.out.print("Hello,World!");
}
}
3.编译javac java文件,会生成一个class文件
4.运行class文件,java 类名,输出:Hello,World!

既是编译型,又是解释型
Java中的注释有三种:
关键字

Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。
标识符注意点
强类型语言:要求变量的使用要严格符合规定,所有变量都需要先定义后使用
Java为强类型语言
弱类型语言
Java的数据类型分为两大类
1.基本类型(primitive type)
a.数值类型:
b.boolean类型
2.引用类型(reference type)
a.类
b.接口
c.数组
位(bit):是计算机内部数据存储的最小单位
字节(byte):是计算机中数据处理的基本单位,习惯上用大写B来表示
1B(byte)=8bit(位)
字符:是指计算机中使用的字母、数字、字和符号
扩展练习:
//银行业务不能用float,一般使用BigDeciaml数学工具类
//float 有限,离散,摄入误差,接近但不等与
float f = 0.1f;
double d = 1.0/10;
System.out.println(f==d);// fasle
所有的字符本质还是数字,使用Unicode编码进行转换
\u表示转义
char c3 = '\u0061';
System.out.println(c3);//a
转义字符:
\t制表符,\n换行符…
Java是强类型语言,所以有时进行运算时,需要用到类型转换
运算中,不同类型的数据线转化为同一类型,然后进行运算。
低 -----------------------------------> 高
byte,short,char-> int -> long-> float -> double
(类型)变量名,由高到低public class Demo05 {
public static void main(String[] args) {
int i = 128;
byte b = (byte)i; //内存溢出,byte范围:-128~127
System.out.println(b);// -128
}
}
注意点:
不能对布尔值进行类型转换
不能把对象类型转换为不相干的类型
在把高容量转换到低容量时,强制转换
转换的实时可能存在内存溢出,或者精度问题
JDK7新特性:数字之间可以用下划线_分割
变量就是可以变化的量
Java是一种强类型语言,每个变量都必须声明其类型
Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
可以使用逗号隔开来声明多个同类型变量,但不建议。
注意:
每个变量都有类型,类型可以是基本类型,也可以是引用类型
变量名必须是合法的标识符
变量声明是一条完整的语句,因此每一个声明都必须以分号结束。
类变量staitc
实例变量,方法外面,类里面,从属于对象
局部变量,方法里面
注:
布尔值的默认值是false
除了基本类型,其余的默认值都为null
常量:初始化后不能再改变值
常量可以理解为一种特殊的变量
关键字为final,一般命名使用大写字母

++和–为一元运算符
短路运算
位运算,根据位来运算
&:相同位的两个数字都为1,则为1;若有一个不为1,则为0。
|:相同位只要一个为1即为1。
异或^:相同位不同则为1,相同则为0。
~:把内存中的0和1全部取反
<<:a << b就表示把a转为二进制后左移b位(在后面添b个0)。例如100的二进制为1100100,而110010000转成十进制是400,那么100 shl 2 = 400。可以看出,a << b的值实际上就是a乘以2的b次方,因为在二进制数后添一个0就相当于该数乘以2。
>>:和>>相似,a >> b表示二进制右移b位(去掉末b位),相当于a除以2的b次方(取整)。
<<<:空位用0补齐
字符串连接符+
多个变量,如果先写字符串,则全部拼接,如""+a+b;若后写字符串,则其余运算完之后再进行拼接,如a+b+""。
为了更好组织类,Java提供包机制,用于区别类名的命名空间
一般利用公司域名倒置作为包名
javadoc命令是用来生成自己的API文档的
输入:/**+回车,来写类和方法的注释
在项目文件中使用cmd:
javadoc -encoding UTF-8 -charset UTF-8 Doc.java
会生成html文档,点开生成的index.html会生成类似官方的API文档
或者可以使用IDEA来进行生成,菜单栏-Tools-Generate JavaDoc
通过Scanner类来获取用户的输入
Scanner s = new Scanner(System.in);
通过Scanner的next()与nextLine()方法获取输入的字符串,在读取前我们一般使用hasNext()与hasNextLine()判断是否还有输入的数据
凡是属于IO流的类如果不关闭会一直占用资源,用完就关掉
scanner.close();
next():
nextLine():
一般的输入字符串都用nextLine()
小练习:
package scanner;
import java.util.Scanner;
public class Demo05 {
public static void main(String[] args) {
// 输入多个数字,并求其总和与平均数,每输入一个数字用回车分割,通过输入非数字来结束输入并输出执行结果
Scanner scanner = new Scanner(System.in);
// 和
double sum = 0;
// 计算输入了多少个数字
int m = 0;
while(scanner.hasNextDouble()){
double x = scanner.nextDouble();
m = m + 1;
sum = sum + x;
System.out.println("你输入了第" + m + "个数据,当前结果sum为:" + sum);
}
System.out.println(m + "个数的和为" + sum);
System.out.println(m + "个数的平均值为" + (sum / m));
scanner.close();
}
}
/**
* 12
* 你输入了第1个数据,当前结果sum为:12.0
* 15
* 你输入了第2个数据,当前结果sum为:27.0
* 20
* 你输入了第3个数据,当前结果sum为:47.0
* a
* 3个数的和为47.0
* 3个数的平均值为15.666666666666666
*
*
*/
JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行,是任何一个算法都离不开的基本算法结构。
if单选择结构
if双选择结构
if多选择结构
if(布尔表达式 1){
//如果布尔表达式1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式3的值为true执行代码
}else{
//如果布尔表达式都不为true执行代码
}
嵌套的if结构
switch多选择结构
switch语句中的变量类型可以是:
switch(expression){
case value:
//语句
break;//可选
case value:
//语句
break;//可选
//可以有任意数量的case语句
default://可选
//语句
}
九九乘法表
public class forDmemo04 {
public static void main(String[] args) {
// 九九乘法表
for (int j = 0; j <= 9; j++) {
for (int i = 1; i <= j; i++) {
System.out.print(j+"*"+i+"="+(j*i)+"\t");
}
System.out.println();
}
}
}
增强for循环:
Java5引入了一种主要用于数组或集合的增强型for循环
Java增强for循环语法格式如下:
//声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
//表达式:表达式是要访问的数组名,或者是返回值为数组的方法
for(声明语句 : 表达式)
{
//代码句子
}
如,遍历数组:
public class forDemo05 {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40, 50};
for (int x: numbers){
System.out.println(x);
}
}
}
break和continue
break强行退出循环,不执行循环中剩余的语句
continue用户终止某次循环,跳过循环中尚未执行的语句,接着进行下一次是否执行循环的判定
练习,打印三角形
public class TestDemo {
public static void main(String[] args) {
// 打印三角形,5行
for (int i = 1; i <= 5; i++) {
for (int j = 5; j >= i; j--) {
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
for (int j = 1; j < i; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
Java方法是语句的集合,它们在一起执行一个功能。
设计方法的原则:保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展。
加法举例:
public class Demo01 {
public static void main(String[] args) {
int sum = add(1, 2);// 实际参数
System.out.println(sum);// 3
}
// 加法,形式参数
public static int add(int a, int b){
return a+b;
}
}
Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段。
一般情况下,定义一个方法包含以下语法:
方法包含一个方法头和一个方法体。下面使一个方法的所有部分:
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
调用方法:对象名.方法名(实参列表)
Java支持两种调用方法的方式,根据方法是否返回值来选择:
int larger = max(30,40);练习,比大小
public class Demo02 {
public static void main(String[] args) {
int max = max(10, 20);
System.out.println(max);// 20
}
// 比大小
public static int max(int num1,int num2){
// 一般return写在最外面,此时定义一个变量
int result = 0;
if(num1==num2){
System.out.println("num1==num2");
// 终止方法
return 0;
}
if (num1>num2){
result = num1;
}else{
result = num2;
}
return result;
}
}
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
方法重载的规则:
实现原理:
方法名称相同时,编译器会根据调用方法参数的个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
在程序运行时传递给它消息,要靠命令行参数给main()函数实现。
例如:
package method;
public class Demo03 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("args["+ i+ "]:"+args[i]);
}
}
}
打开文件所在路径,在路径位置输入cmd
先进行编译:javac Demo03.java
回退到src目录下才可以执行:cd ../
运行并传参:java method.Demo03 this is kkk

可看到参数已传入
(不定向参数)
其本质为数组,如:
public class Demo04 {
public static void main(String[] args) {
Demo04 demo04 = new Demo04();
demo04.test(1,2,3,4,45,5);
// 输出:
// 1
// 2
// 3
// 4
// 45
// 5
}
public void test(int... i){
System.out.println(i[0]);
System.out.println(i[1]);
System.out.println(i[2]);
System.out.println(i[3]);
System.out.println(i[4]);
System.out.println(i[5]);
}
}
A方法调用A方法,自己调用自己
java使用的都是栈机制
一般不使用递归,小量计算时才使用
数组是相同类型数据的有序集合
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
如:
public class ArrayDemo01 {
public static void main(String[] args) {
int[] nums;// 1.声明一个数组
nums = new int[10];// 2.创建一个数组
//或者声明和创建可以写在一起???
// 3.给数组元素中赋值
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
nums[3] = 4;
nums[4] = 5;
nums[5] = 6;
nums[6] = 7;
nums[7] = 8;
nums[8] = 9;
nums[9] = 10;
// 计算所有元素的和
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum = sum + nums[i];
}
System.out.println(sum);//55
}
}
Java内存:
只要使用new,都是保存在堆中
public class ArrayDemo02 {
public static void main(String[] args) {
//静态初始化
int[] a = {1,2,3,4,5,6,7,8};
System.out.println(a[0]);
//动态初始化,包含默认初始化
int[] b = new int[10];
b[0] = 10;
System.out.println(b[0]);
//默认初始化
System.out.println(b[3]);// 0
}
}
数组边界
下标的合法区间[0,length-1]
练习
public class ArrayDemo04 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
//
// //JDK1.5,遍历
// for(int array : arrays){
// System.out.println(array);
// }
// printArray(arrays);
int[] reverse = reverse(arrays);
printArray(reverse);
}
//反转数组
public static int[] reverse(int[] arrays) {
int[] result = new int[arrays.length];
//反转操作
for (int i = 0,j=result.length-1; i < arrays.length; i++,j--) {
result[j] = arrays[i];
}
return result;
}
//打印数组元素
public static void printArray(int[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]+" ");
}
}
}
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
int a[][] = new int[2][5];
数组的工具类java.util.Arrays
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直击使用类名进行调用
具有以下常用功能:
时间复杂度为O(n²)
public class ArrayDemo07 {
public static void main(String[] args) {
int[] a = {1,4,5,6,72,2,2,2,25,6,7};
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
}
// 冒泡排序
public static int[] sort(int[] array){
int temp = 0;
for (int i = 0; i < array.length-1; i++) {
// 减少没有意义的比较
boolean flag = false;
for (int j = 0; j < array.length-1-i; j++) {
if(array[j+1]<array[j]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flag = true;
}
}
if(flag == false){
break;
}
}
return array;
}
}
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方式是:
如图,左边是原始数组,右边是稀疏数组


代码:
public class ArrayDemo08 {
public static void main(String[] args) {
//1.创建一个二维数组11*11 0:没有棋子 1:黑棋 2:白棋
int[][] array1 = new int[11][11];
// 第2行第3列
array1[1][2] = 1;
// 第3行第4列
array1[2][3] = 2;
//输出原始的数组
System.out.println("输出原始的数组:");
for (int[] ints : array1) {
for(int anInt:ints){
System.out.print(anInt+"\t");
}
System.out.println();
}
System.out.println("================");
//转换为稀疏数组保存
//获取有效值的个数
int sum = 0;
for (int i = 0; i <11 ; i++) {
for (int j = 0; j <11 ; j++) {
if(array1[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值的个数:"+sum);
//2.创建一个稀疏数组的数组
// 有效值的个数+1就是稀疏数组的行数,需要行、列、值3列
int[][] array2 = new int[sum+1][3];
// 第一行
array2[0][0] = 11;//存储行数
array2[0][1] = 11;//存储列数
array2[0][2] = sum;//存储有效值个数
//遍历二维数组,将非零的值存放在稀疏数组中
int count = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if(array1[i][j]!=0){
count++;
// 每行的第一个位置存横坐标
array2[count][0] = i;
// 每行的第二个位置存纵坐标
array2[count][1] = j;
// 每行的第三个位置存当前值
array2[count][2] = array1[i][j];
}
}
}
//输出稀疏数组
System.out.println("稀疏数组:");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0]+"\t"
+array2[i][1]+"\t"
+array2[i][2]+"\t");
}
System.out.println("================");
System.out.println("根据稀疏数组进行还原:");
// 1.读取稀疏数组
int[][] array3 = new int[array2[0][0]][array2[0][1]];// 数组的长、宽
// 2,给其中的元素还原它的值
for (int i = 1; i < array2.length; i++) {//从i=1开始,第一行信息不用读
// 根据上面稀疏数组array2来存到新的数组array3中
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
// 3.打印
System.out.println("输出还原的数组:");
for (int[] ints : array3) {
for(int anInt:ints){
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}
/**
* 输出原始的数组:
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 1 0 0 0 0 0 0 0 0
* 0 0 0 2 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* ================
* 有效值的个数:2
* 稀疏数组:
* 11 11 2
* 1 2 1
* 2 3 2
* ================
* 根据稀疏数组进行还原:
* 输出还原的数组:
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 1 0 0 0 0 0 0 0 0
* 0 0 0 2 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
* 0 0 0 0 0 0 0 0 0 0 0
*
*
*/
面向过程思想:第一步做什么,第二步做什么…适合处理较为简单的问题。
面向对象思想:分类的思维模式,每个类进行单独思考。最后才对某个分类下的细节进行面向过程的思索。适合处理复杂的、需要多人协作的问题。
Java的核心思想就是面向对象编程OOP(Object-Oriented Programming)
面向对象编程的本质就是:以类的方式组织代码,以对象的方式组织(封装)数据。
面向对象的三大特性:
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
从代码运行角度考虑是先有类后有对象。类是对象的模板。
非静态方法调用,需要将类实例化,使用new关键字.
如:
Student.java
package oop.demo01;
// 学生类
public class Student {
// // 静态方法
// public static void say(){
// System.out.println("学生说话");
// }
// 非静态方法
public void say(){
System.out.println("学生说话");
}
}
同级目录下:
Demo02.java
package oop.demo01;
public class Demo02 {
public static void main(String[] args) {
// 静态方法调用
// Student.say();
// 输出:学生说话
// 非静态方法调用,需要将类实例化,使用new关键字
// 对象类型 对象名 = 对象值
Student student = new Student();
// 调用
student.say();
// 输出:学生说话
}
}
static静态方法和类一起加载,类存在时就存在。但非静态方法和对象有关,对象创建后才存在(类实例化为对象)。
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是不能代表某一个具体的事物。
对象是抽象概念的具体实例。
创建与初始化对象
一个类中只包含属性和方法。
类中的构造器也叫构造方法,是在进行创建对象的时候必须要调用的。
构造器有以下特点:
一个类如果什么都不写,也会存在一个构造器(构造方法)。
Person.java
package oop.demo02;
public class Person {
}
Application.java
package oop;
public class Application {
public static void main(String[] args) {
// new实例化了一个对象
Person person = new Person();
}
}
运行Application.java文件
在项目目录下的out文件夹下打开生成的Person.class文件,可看到默认自动生成了 public Person()方法,即构造方法。
package oop.demo02;
public class Person {
public Person() {
}
}
Person.java
package oop.demo02;
public class Person {
// 一个类即使什么都不写,它也会存在一个方法
// 显示的定义构造器
String name;
// 实例化初始值
public Person(){
}
// 无参构造
// public Person(){
// this.name = "kkk";
//
// }
// 有参构造:一旦定义了有参构造,无参构造就必须显示定义一个无参构造
public Person(String name){
this.name = name;
}
}
Application.java
package oop.demo02;
public class Application {
public static void main(String[] args) {
// new 实例化了一个对象
Person person = new Person("kkk");
System.out.println(person.name);
// 输出:kkk
}
}
运行Application.java文件,输出kkk。
ALT+INSERT-点Constructor-选中-OK,生成有参构造器。
ALT+INSERT-点Constructor-选中-Select None,生成无参构造器。
程序设计追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装就是数据的隐藏。通常,应禁止直接访问一个对象中的数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
private私有属性,使用一些public的get/set方法便可以操作这些属性。
ALT+INSERT-Getter and Setter-选中属性-OK,自动生成get和set方法。
Stundent.java
package oop.demo04;
public class Student {
// 属性私有
// 名字
private String name;
// 学号
private int id;
// 性别
private char sex;
//年龄
private int age;
// 提供一些可以操作这个属性的方法
// 提供一些public的get、set方法
// get 获得这个数据
public String getName(){
return this.name;
}
// set 给这个数据设置值
public void setName(String name){
this.name = name;
}
// ALT+INSERT-Getter and Setter-选中属性-OK,自动生成get和set方法。
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
// 封装过的可以做一下安全性的检查
public void setAge(int age) {
if (age>120 || age<0) {
this.age =3;
}else {
this.age = age;
}
}
}
Application.java
package oop;
import oop.demo04.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("kkk");
System.out.println(s1.getName());
// 输出:kkk
// 年龄不合逻辑,可在封装中做检查
s1.setAge(999);
System.out.println(s1.getAge());
// 输出:3
}
}
封装的作用:
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
extends的意思是“扩展”,子类是父类的扩展。
Java中类只有单继承,没有多继承。(一个儿子只能有一个父亲,一个父亲可以有多个儿子)
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的两个类,一个为子类(派生类),一个父类(基类)。子类继承父类,使用关键字extends来表示。
子类和父类之间,从意义上讲具有"is a"的关系。
子类继承父类,就会拥有父类的全部方法。但父类私有的private无法继承,一般属性才设置为私有,但可以设置get和set方法来进行操作。
Person.java
package oop.demo05;
import com.sun.org.apache.xpath.internal.SourceTree;
// Person 人 : 父类
public class Person {
// 父类私有的private无法继承,一般属性才设置为私有,但可以设置get和set方法来进行操作。
private int money = 10_0000_0000;
public void say(){
System.out.println("说了一句话");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
Person.java
package oop.demo05;
// 学生 is 人 : 派生类,子类
// 子类继承了父类,就会拥有父类的全部方法
public class Student extends Person {
}
Application.java
package oop;
import oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
// 输出:说了一句话
System.out.println(student.getMoney());
// 输出:1000000000
}
}
CTRL+H显示当前类继承树
在Java中,所有的类,都默认直接或间接继承Object类。
super代表父类的,this为当前的。
super注意点:
Person.java
package oop.demo05;
import com.sun.org.apache.xpath.internal.SourceTree;
// Person 人 : 父类
public class Person {
// 类中有默认的构造器,调用一个对象会先走无参构造器
public Person() {
System.out.println("Person无参构造执行了");
}
protected String name = "kkk";
public void print(){
System.out.println("Person");
}
}
Student.java
package oop.demo05;
// 学生 is 人 : 派生类,子类
// 子类继承了父类,就会拥有父类的全部方法
public class Student extends Person {
// 默认调用了父类的无参构造,调用父类的构造器,必须要在子类构造器的第一行
// super();//可写可省略
public Student() {
System.out.println("Student无参构造执行了");
}
private String name = "kun";
public void print(){
System.out.println("Student");
}
public void test1(){
print();
// 输出:Student
this.print();
// 输出:Student
super.print();
// 输出:Person
}
public void test(String name){
System.out.println(name);
// 输出:kill
// Student类中的name
System.out.println(this.name);
// 输出:kun
// 父类Person类中的name
System.out.println(super.name);
// 输出:kkk
}
}
Application.java
package oop;
import oop.demo05.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
// 输出:
// Person无参构造执行了
// Student无参构造执行了
student.test("kill");
student.test1();
}
}
super和this的区别:
this();调用本类的构造super();调用父类的构造B.java
package oop.demo05;
// 重写都是方法的重写,和属性无关
public class B {
public static void test(){
System.out.println("B=>test()");
}
}
A.java
package oop.demo05;
public class A extends B{
public static void test(){
System.out.println("A=>test()");
}
}
Application.java
package oop;
import oop.demo05.A;
import oop.demo05.B;
public class Application {
public static void main(String[] args) {
A a = new A();
a.test();
// 输出:A=>test()
// 父类的引用指向了子类
// 若为静态方法:方法的调用只和左边定义的数据类型有关,和右边new的无关
B b = new A();
b.test();
// 输出:B=>test()
}
}
运行Application.java
输出:
A=>test()
B=>test()
将方法写为非静态,并在A类中进行方法的重写。
B.java
package oop.demo05;
// 重写都是方法的重写,和属性无关
public class B {
public void test(){
System.out.println("B=>test()");
}
}
A.java
package oop.demo05;
public class A extends B{
// ALT+INSERT,选择Override Methods
@Override
public void test() {
System.out.println("A=>test()");
}
}
Application.java
package oop;
import oop.demo05.A;
import oop.demo05.B;
public class Application {
public static void main(String[] args) {
A a = new A();
a.test();
// 输出:A=>test()
// 父类的引用指向了子类
// 若为静态方法:方法的调用只和左边定义的数据类型有关,和右边new的无关
// 非静态:重写
// 子类重写了父类的方法(A重写了B的方法)
B b = new A();
b.test();
// 输出:A=>test()
}
}
此时运行Application.java
输出:
A=>test()
A=>test()
非静态方法才可以进行重写。
重写的前提是需要有继承关系,子类重写父类的方法。
子类和父类的方法必须一致,方法体不同。
重写都是方法的重写,和属性无关。
为什么需要重写:父类的功能子类不一定需要或不一定满足。
重写快捷键:ALT+INSERT,选择Override Methods。
不能被重写的情况:
多态可实现动态编译,动态编译:类型在执行过程中才可以确定。增强可扩展性。
多态:同一方法可以根据发送对象的不同而采取多种不同的行为方式。
一个对象的实际类型是确定的,但可以指向对象的引用类型有很多。
Person.java
package oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
Student.java
package oop.demo06;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
Application.java
package oop;
import oop.demo06.Person;
import oop.demo06.Student;
public class Application {
public static void main(String[] args) {
// 一个对象的实际类型是确定的
// new Student();
// new Person();
// 对象指向的引用类型不确定
// 实际类型都是确定的,都为Student,但指向这个对象的引用类型可以是任意的父类型
// Student能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
// 父类的引用指向子类的类型
// Person父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
// Object类是所有类的祖宗类
Object s3 = new Student();
// 子类重写了父类的方法,执行子类的方法
s2.run();
// 输出:son
s1.run();
// 输出:son
// 对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
// s2.eat();不能调用,会报错,
s1.eat();
// 输出:eat
}
}
多态存在的条件:
多态注意事项:
instanceof:判断前面的对象是否属于后面的类,或者属于其子类。
引用类型变量(object) instanceof 类(class)
Person.java
package oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
Student.java
package oop.demo06;
public class Student extends Person{
public void go(){
System.out.println("go");
}
}
Teacher.java
package oop.demo06;
public class Teacher extends Person{
}
Application.java
package oop;
import oop.demo06.Person;
import oop.demo06.Student;
import oop.demo06.Teacher;
public class Application {
public static void main(String[] args) {
// Object > String
// Object > Person > Teacher
// Object > Person > Student
Object object = new Student();
System.out.println(object instanceof Student);// true
System.out.println(object instanceof Person);// true
System.out.println(object instanceof Object);// true
System.out.println(object instanceof Teacher);// False
System.out.println(object instanceof String);// False
System.out.println("==========================");
Person person = new Student();
System.out.println(person instanceof Student);// true
System.out.println(person instanceof Person);// true
System.out.println(person instanceof Object);// true
System.out.println(person instanceof Teacher);// False
//System.out.println(person instanceof String);// 编译报错
System.out.println("==========================");
Student student = new Student();
System.out.println(student instanceof Student);// true
System.out.println(student instanceof Person);// true
System.out.println(student instanceof Object);// true
//System.out.println(student instanceof Teacher);// 编译报错
//System.out.println(student instanceof String);// 编译报错
//System.out.println(X instanceof Y);// 能否编译通过,取决于X和Y是否存在父子关系
}
}
类型之间的转化:
在Application.java中进行修改:
package oop;
import oop.demo06.Person;
import oop.demo06.Student;
public class Application {
public static void main(String[] args) {
// 类型之间的转化: 父 子
// Person > Student
Person obj = new Student();
// 高转低
//student.go();// 会报错
// 将obj这个对象转换为Student类型,就可以使用Student类型的方法
Student student = (Student) obj;
student.go();
// 输出:go
// 或者直接:
((Student)obj).go();
// 输出:go
// 低转高,可以自动转换
// 子类转换为父类,可能丢失自己的本来的一些方法
Student student1 = new Student();
student1.go();
// 输出:go
// 父类引用指向子类的对象
Person person = student;
//person.go();// 此时调用不了
}
}
静态属性和静态方法:
Student.java
package oop.demo07;
public class Student {
// 静态变量
private static int age;
// 非静态变量
private double score;
public void run(){
}
public static void go(){
}
public static void main(String[] args) {
Student s1 = new Student();
// 类变量
System.out.println(Student.age);
// 通过对象调用方法
System.out.println(s1.score);
// 非静态方法,new出来才可以调用
new Student().run();
// 静态方法可以直接调用
Student.go();
}
}
静态代码块:
Person.java
package oop.demo07;
public class Person {
// 2:用来赋初始值
{
System.out.println("匿名代码块");
}
// 1:只执行一次
static {
System.out.println("静态代码块");
}
// 3
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("==============");
Person person2 = new Person();
// 运行,看加载顺序
/*
输出:
静态代码块
匿名代码块
构造方法
==============
匿名代码块
构造方法
*/
}
}
静态导入包:
package oop.demo07;
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
System.out.println(random());
// 输出:0.008421153996752806
System.out.println(PI);
// 输出:3.141592653589793
}
}
通过final修饰的类不能被继承(没有子类)。
abstract修饰的方法为抽象方法,abstract修饰的类为抽象类。
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
抽象类不能使用new关键字来创建对象,它是用来让子类继承的。
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
抽象类中可以写普通方法,抽象方法必须在抽象类中。
Action.java
package oop.demo08;
// 抽象类
public abstract class Action {
// 起到约束作用,有人帮我们实现
// abstract,抽象方法,只有方法名字,没有方法的实现
public abstract void doSomething();
}
A.java
package oop.demo08;
// 抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非子类也为abstract
public class A extends Action{
@Override
public void doSomething() {
}
}
递进关系:
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。
接口的本质是契约,制定好后大家都遵守。
OO的精髓是对抽象的抽象,接口最能体现这一点。
实现了接口的类,就需要重写接口中的方法。
接口可以实现多继承。
UserService.java
package oop.demo09;
// 接口都需要有实现类
public interface UserService {
// 属性默认为常量,默认为public static final,可省略,但一般不在接口中定义
int AGE = 99;
// 接口中的所有定义的方法都是抽象的:默认为public abstract,可省略
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
TimeService.java
package oop.demo09;
public interface TimeService {
void timer();
}
UserServiceImpl.java
package oop.demo09;
// 类实现接口,implements 接口
// 实现了接口的类,就需要重写接口中的方法
// 利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
接口的作用:
内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对于B类来说就是外部类了。
1.成员内部类
Outer.java
package oop.demo10;
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner {
public void in(){
System.out.println("这是内部类的方法");
}
// 内部类可以获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
Application.java
package oop;
import oop.demo10.Outer;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
// 通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
// 输出:这是内部类的方法
inner.getID();
// 输出:10
}
}
2.静态内部类
Outer.java
package oop.demo10;
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public static class Inner {
public void in(){
System.out.println("这是内部类的方法");
}
// 静态内部类无法直接访问外部类非静态的属性
// 内部类为static时,无法访问
// public void getID(){
// System.out.println(id);
// }
}
}
3.局部内部类
Outer.java
package oop.demo10;
public class Outer {
// 局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
4.匿名内部类
Test.java
package oop.demo10;
public class Test {
public static void main(String[] args) {
// 没有名字来初始化类,不用将实例保存到变量中
new Apple().eat();
new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println(1);
}
}
interface UserService{
void hello();
}
异常发生在程序运行期间,它影响了正常的程序执行流程。
三种类型的异常:
Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
在Java API中已经定义了许多异常类,这些异常类分类两大类,错误Error和异常Exception。

ERROR:
Exception:
异常处理机制:
异常处理的5个关键字:
try、catch、finally、throw、throws
Test.java
package exception;
public class Test {
public static void main(String[] args) {
int a = 1;
int b = 0;
try { // 监控区域
System.out.println(a/b);
}catch (ArithmeticException e){ // catch捕获异常,(想要捕获的异常类型)
System.out.println("程序出现异常,变量b不能为0");
}finally { // 处理善后工作,不管是否出现异常都会执行
System.out.println("finally");
}
}
}
throw、throws主动抛出异常,throw一般用在方法中,throws用在方法上。
Test.java
package exception;
public class Test {
public static void main(String[] args) {
// 此处的算术异常ArithmeticException属于运行时异常,正常情况下此异常不需要程序抛出,会自动抛出
try {
new Test().test(1, 0);
} catch (ArithmeticException e) {
throw new RuntimeException(e);
}
}
// throws 假设在这个方法中,处理不了这个异常,方法上抛出异常
public void test(int a,int b) throws ArithmeticException{
if (b==0){
throw new ArithmeticException();// throw 主动抛出异常,一般在方法中使用
}
System.out.println(a/b);
}
}
捕获多个异常,可以通过写多个catch来实现,层级结构高的异常写在后面,finally可以没有。
CTRL+ALT+T,选择try catch,可以生成对应代码块
自定义异常
用户自定义异常,只需要继承Exception类。
在程序中使用自定义异常,分为以下步骤:
MyException.java
package exception.demo02;
// 自定义的异常类
public class MyException extends Exception {
// 传递数字,若>10,则抛出异常
private int detail;
public MyException(int a) {
this.detail = a;
}
// toString,进行输出,ALT+INSERT-toString
// 异常的打印信息
@Override
public String toString() {
return "MyException{" + detail + '}';
}
}
Test.java
package exception.demo02;
public class Test {
// 可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:"+a);
if(a>10){
throw new MyException(a);
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
System.out.println("MyException:"+e);
}
}
/**
* 输出:
* 传递的参数为:11
* MyException:MyException{11}
*/
}
异常处理经验:
1.注:
public static void main(String[] args) {
}
的IDEA快捷键为psvm
System.out.println();
的IDEA快捷键为sout,可以直接输出内容.sout
3.CTRL+D复制当前行到下一行
4.100.for生成
for (int i = 0; i < 100; i++) {
}
fori生成
for (int i = 0; i < ; i++) {
}
ALT+INSERT-点Constructor-选中-OK,生成有参构造器。
ALT+INSERT-点Constructor-选中-Select None,生成无参构造器。
ALT+INSERT-Getter and Setter-选中属性-OK,自动生成get和set方法。
6.CTRL+H显示当前类继承树
7.重写快捷键:ALT+INSERT,选择override。
8.CTRL+ALT+T,选择try catch,可以生成对应代码块
9.选中变量,SHIFT+F6,进行更改,回车,所有使用到的地方便都进行了修改。