本篇博文目录:

  • 1.什么是JDK,JRE,JVM?
  • 2.JAVA编译过程?
  • 3.标识符(命名规范)
  • 4.关键字
  • 5.数据类型
  • (1)定义
  • (2)8种基本数据类型
  • 6. 常量,变量(访问修饰符)
  • (1) 常量
  • (2) 变量
  • (3)局部变量和全局变量
  • (4)访问权限
  • 7. 数据类型转换(自动类型转换,强制类型转换)
  • (1).自动类型转换(隐式转换)
  • (2).强制类型转换(显示转换)
  • 8.运算符
  • (1) 关于++和- -
  • (2)关于&&,||与&,I
  • (3)关于三目运算
  • 9.表达式,顺序,选择(if,if else else if/switch),循环(while(){}; do{}while();for ;for增强)
  • (1)表达式
  • (2)选择
  • (2)循环
  • 10.数组
  • (1)声明数组变量
  • (2)创建数组
  • (3)数组的访问
  • 11.OOP编程
  • (1) 方法
  • (2).类
  • (3).对象
  • (4)三大特性(封装,继承,多态)
  • 12.异常机制
  • 13.集合(Set,List,Map)
  • 14.IO流
  • 15.多线程
  • 16.网络编程(TCP【重点】;UDP)


1.什么是JDK,JRE,JVM?

  • JDK:是程序员使用java语言编写java程序所需的开发工具包(包括JRE,工具等),是提供给程序员使用的。
  • JRE:是用户运行Java程序需要的运行环境(java虚拟机,java基础类库)。
  • JVM:JVM虚拟机,
    用来解释执行字节码文件(class文件:通过Javac翻译.java得到),java的跨平台就是通过JVM来实现的。

Javaee期末大族业_Javaee期末大族业

2.JAVA编译过程?

JAVA编译过程:Java编译程序(javac)将Java源程序(HelloWorld.java),翻译成Java字码文件(HelloWorld.class),JVM虚拟机对HelloWorld.class进行解释执行。

Javaee期末大族业_后端_02

下面通过CMD的方式执行一个HelloWorld的demo来体验一下这个过程。

过程如下🔻:

  • 用记事本创建一个HelloWorld.java的文件(—>另成为—>数据类型选为所有—>输入HelloWorld.java保存)
  • 进入dos界面(Windows+R输入cmd),cd进入到桌面(HelloWorld.java在哪里就进入到哪里),输入Javac HelloWorld.java
  • 此时对应的目录下就会生成一个HelloWorld.Class的文件
  • 输入java HelloWorld

3.标识符(命名规范)

用来定义变量,方法,类等要素命名时使用的字符串序列。

规则:

  • 应以字母,下划线,$符号开头
  • 应以字母,下划线,$符号或数字组成
  • 对大小写敏感,长度无限制
  • 不能使用关键字

非法标识名举例:Class(关键字),9aa(不能以数字开头),Hee LL(不能出现空格)

4.关键字

有特殊含义的、被保留的、不能随意使用的字符(小写)。

Javaee期末大族业_java_03


Javaee期末大族业_数据类型_04

5.数据类型

(1)定义

Java语言是一种强类型语言,所谓的强制类型指的是对于每一种数据都有明确的数据类型,每个数据类型占多少个字节(JavaScripct中的变量都是通过Var进行声明,没有明确指定数据类型,所以JS不是一种强制类型的语言.我们常称为弱类型语言)。

在Java中数据类型可分为二类,基本数据类型引用数据类型(下面只介绍8种基本数据类型 ,这8种数据类型也是最核心的,必须掌握的)。

Javaee期末大族业_Javaee期末大族业_05

(2)8种基本数据类型
  • 整数(4种:byte,short,int(默认),long;字节数分别为:1B,2B,4B,8B)
  • 浮点数(float,double(默认);字节数分别为:4B,8B)
  • 字符(char;字节数为:2B)
  • 布尔(boollean;字节数分别为:1B)
  • 关于取值范围(除字符和布尔外):-2(n-1)~2n -1 n:位数
  • 字符取值范围:0~2n -1 布尔:true和false

Javaee期末大族业_Javaee期末大族业_06

6. 常量,变量(访问修饰符)

(1) 常量

程序在执行过程中其值是不可以改变的量叫做常量

语法:【访问权限】final 数据类型 常量名=初始值
例子:public final int COUNT=0;

注意事项

  • 在定义常量时就需要对该常量进行初始化。
  • final 关键字不仅可以用来修饰基本数据类型的常量,还可以用来修饰对象的引用或者方法。
  • 为了与变量区别,常量取名一般都用大写字符。

常量的初始化,还可以放在类构造器中进行初始化(该常量未被static修饰):

Javaee期末大族业_数据类型_07


二种初始化的方式只能使用其中的一种,不然不符合语法规则:

Javaee期末大族业_开发语言_08

引用类型的常量,不可变指的是地址不可变,但是对象里的值是可变的:

Javaee期末大族业_Javaee期末大族业_09

测试类代码(引用类型的常量,不可变指的是地址不可变):

Javaee期末大族业_Javaee期末大族业_10


测试类代码(但是对象里的值是可变的)

Javaee期末大族业_java_11


运行效果:

Javaee期末大族业_后端_12

(2) 变量

程序在执行过程中其值是可以改变的量叫做变量

语法:【访问权限】 数据类型 变量名【=初始值,可以初始化,也可以不用进行初始化】;

下图给出的是8种数据类型,所占存储空间,表示的范围和默认值:

Javaee期末大族业_java_13


注意:

  • 局部变量必须进行初始化即赋值,才能使用(它没有默认值)
  • 全局变量可以不进行初始化,使用对应数据类型的默认值(未规定数据类型的时候,整型默认:int,浮点默认:double)。

局部变量必须进行初始化:

Javaee期末大族业_数据类型_14


全局变量可以不进行初始化,使用对应数据类型的默认值:

Javaee期末大族业_Javaee期末大族业_15


运行效果:

Javaee期末大族业_Javaee期末大族业_16

(3)局部变量和全局变量

局部和全局意思可理解为该变量可访问的范围,局部变量可访问为对应所在{}代码块的区域,而全局变量在整个Class的{}代码块下,意思就是在本类都可以进行访问(无需关注访问权限),并且全局变量可以被其他类(同包,非同包)进行访问,前提是访问权限足够(该全局变量足够开放)。

public class demo{
  int a;//全局变量
  public void start(){
		int c;//局部变量
  }
  
  public void start2(int c){ //c 局部变量
		
  }

}
(4)访问权限

主要用于其他类(本包,非本包,非本包子类,非本包非子类)对目标类进行访问时根据权限来看该类是否可以进行访问。

Javaee期末大族业_后端_17

注意:

  • default:表示不加任何访问修饰符(通常称为“默认访问权限“或者“包访问权限”)

7. 数据类型转换(自动类型转换,强制类型转换)

(1).自动类型转换(隐式转换)

当数据类型不一样时,将会发生数据类型转换。

  • 特点:代码不需要进行特殊处理,自动完成。
  • 规则:数据范围从小到大。

🔻(右面100是未规定数据类型,即该数据类型默认为int,左边为long,右边int数据类型的数据放入long(小->大)发生了自动类型转换。)

long num=100;

右面2.5F规定了数据类型为float,(如果不加F表示数据类型为double),左面数据类型为double(小->大)发送了自动类型转换。

double num2 = 2.5F;

由于浮点数默认使用double,在使用float的时候需要在右侧加上f,不然会报错:

Javaee期末大族业_数据类型_18

备注:关于什么是小什么是大,其实指的就是该数据类型所占的字节数大小。

(2).强制类型转换(显示转换)

如果数据类型没有发生自动转换,也可以通过强制类型进行转换但是这样可能会导致数据丢失。

  • 特点:代码需要进行特殊的格式处理,不能自动完成。
  • 格式:范围小的类型 范围小的变量名= (范围小的类型)原本范围大的数据;

🔻(右面数据类型为long,左面数据类型为int(大->不发生自动类型转换),(int)表示该long数据类型强制转换为int。)

int num = (int) 100L ;

备注:

  • 强制类型转换一般不推荐使用,因为有可能发生精度损失、数据溢出。
  • byte/short/char这三种类型都可以发生数学运算,例如加法“+”
  • byte/short/char这三种类型在运算的时候,都会被首先提升成为int类型,然后再计算。

这里并不是四舍五入,所有的小数位都会被舍弃掉:

Javaee期末大族业_后端_19


运行效果:

Javaee期末大族业_数据类型_20


🔻 int和浮点类型之间可以进行强制类型转换

Javaee期末大族业_java_21

运行效果:

Javaee期末大族业_java_22

🔻char可以通过强制类型转换为int,对应的值为字符的ASCLL的值

Javaee期末大族业_数据类型_23


Javaee期末大族业_数据类型_24

🔻(对于byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围,那么java编译器将会自动隐含地补上一个(byte)(short)(char)。)

  • 如果没有超过左侧的范围,编译器自动隐含地补上(byte)进行强转。
byte num1 = /*(byte)*/ 30; //右侧没有超过左侧的范围
        System.out.println(num1); // 30
  • 如果右侧超过了左侧范围,那么编译器报错。

Javaee期末大族业_Javaee期末大族业_25


8.运算符

运算符 用于连接 表达式 的 操作数,并对操作数执行运算。

运算符速查表:

Javaee期末大族业_数据类型_26


运算符优先级:

Javaee期末大族业_java_27

(1) 关于++和- -

count++:表示先执行运算 ++count:表示先运算执行 备注:“--”同理

//关于count++
					 int count=0;
					 System.out.println(count++);//0
					 System.out.println(count);//1
					 
					 int count1=0;
					 count1++;
					 System.out.println(count1);//1
					 
					 
					//关于++count
					int count2=0;
					System.out.println(++count2);//1
					
					int count3=0;
					++count3;
					System.out.println(count3);//1

注意:++(i++)这种写法不存在!

Javaee期末大族业_数据类型_28

(2)关于&&,||与&,I

(&&,||)表示如果前面一项表达式已经满足要求了后面一项的表达式就无需再进行相应的判断了。

如下:count=100已经满足表达式1(count>=100)对于表达式2(count<500)就不用进行判断,但是条件为“|”时,表达式1和表达式2都要进行运算(这就是短路与与短路或的作用)。

int count=100;
					if (count>=100||count<500) {
						System.out.println("执行");
					}
(3)关于三目运算

三目运算表达式进行判断之后,表达式为true返回 “:” 左面的值,如果为false返回 “:”

int count=100;
					boolean result=(count==100?true:false);
					System.out.println(result);//true

9.表达式,顺序,选择(if,if else else if/switch),循环(while(){}; do{}while();for ;for增强)

(1)表达式

表达式运算后的结果要么为真要么为假

语法:变量/常量 比较运算 变量/常量 【逻辑运算】 变量/常量 比较运算 变量/常量

🔻(下面的表达式a>b,a<B可以分别看作一个小的表达式,整体可以看作是一个大的表达式)。
例子:a>b&&a<B

(2)选择
if(表达式){
  //执行符合表达式要求的代码
}
if(表达式1){
 //执行符合表达式1的代码
}else if(表达式2){
//执行符合表达式2的代码
}
if(表达式1){
 //执行符合表达式1的代码
}else if(表达式2){
//执行符合表达式2的代码
}else{
  //执行不满足所有不符合表达式1和表达式2的代码
}

🔻注意: switch中只有当遇到break的时候才退出(意思就是当switch满足情况1的情况下,执行情况1的代码,但是情况1结尾处如果没有break就继续执行情况2的代码直到遇到break才退出)。

switch(变量/常量){
		case 变量/常量(同一数据类型):
		//执行满足该情况的代码
		break;
		case 变量/常量(同一数据类型):
		 //执行满足该情况的代码
		break;
		default:
		 //执行不满足所有上面情况的代码
		break;
}

在JDK1.8中,switch支持的参数如下图所示:

Javaee期末大族业_数据类型_29

(2)循环
  • break:结束本循环
  • continue:结束本次循环

i的变化:i=0,1,2,3…19 当i=20的时候执行i<20不满足本次循环结束

for(int i=0;i<20;i++){
  //执行20次 i的变化:i=0,1,2,3.....19 当i=20的时候执行i<20不满足本次循环结束
}

备注:for的执行顺序为i = 0,然后i<20,方法题{}中的代码,i++,再然后执行i<20,方法题{}中的代码,i++,后面按到此顺序循环直到i<20不满足条件为止。

for(集合泛型数据类型:集合)增强

ArrayList<String> arrayList=new ArrayList<>();
			arrayList.add("1");
			arrayList.add("2");
			arrayList.add("3");
			arrayList.add("4");
			for(String aString:arrayList){
				System.out.println(aString);//允许情况:1 2 3  4
				
			}

备注:泛型类型指的是一组数据集合中共同采用的数据类型,是对一组数据类型的限定。

while(表达式)直到表达式为false才停止循环

while (表达式) {
			//直到表达式为false停止循环
}

do{}while(表达式);先执行一次,然后当表达式为false时停止循环

do{
		//先执行一次,然后当表达式为false时停止循环		
  }while(表达式);

10.数组

存放一组相同数据类型的数据。

(1)声明数组变量

首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:

  • 数据类型[] 数组名; // 首选的方法
  • 数据类型 数组名[]; // 效果相同,但不是首选方法

实例:

  • double[] myList; // 首选的方法
  • double myList[]; // 效果相同,但不是首选方法
(2)创建数组

下面的10表示数组的长度
myList= new double[10];
另外一种创建数组的方式:

数据类型[] 数组名= {value0, value1, ..., valuek};
(3)数组的访问

数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 arrayRefVar.length-1。

🔻(表示访问数组myList索引为0的对应数据。)

myList[0];

🔻(myList.length:表示获取myList数组的长度)

myList.length;

实例:

public class TestArray {
   public static void main(String[] args) {
      // 数组大小
      int size = 10;
      // 定义数组
      double[] myList = new double[size];
      myList[0] = 5.6;
      myList[1] = 4.5;
      myList[2] = 3.3;
      myList[3] = 13.2;
      myList[4] = 4.0;
      myList[5] = 34.33;
      myList[6] = 34.0;
      myList[7] = 45.45;
      myList[8] = 99.993;
      myList[9] = 11123;
      // 计算所有元素的总和
      double total = 0;
      for (int i = 0; i < size; i++) {
         total += myList[i];
      }
      System.out.println("总和为: " + total);
   }
}

11.OOP编程

(1) 方法

避免代码臃肿,将某一个操作的代码移到定义的方法中,当用户需要执行该操作时,只需要调用该方法即可,程序就会进入到方法中去执行该操作的代码。

方法语法如下:

[访问权限] [static] [..] 返回值类型  方法名([形参1][形参2]..[形参n]){
        //当方法被使用时执行代码块的代码
        return 返回值类型;
}

例子:

Javaee期末大族业_数据类型_30


运行效果:

Javaee期末大族业_java_31

关于方法的返回值类型为void:

表示没有返回值,不用写 return 返回值类型 数据类型就是基本数据类型或者引用数据类型,但是数据类型不一致会报错。

返回数据类型为void就不用写 return 返回值类型:

Javaee期末大族业_后端_32

返回数据类型(int)和返回的数据类型(String)不一致会报错:

Javaee期末大族业_开发语言_33

(2).类

类是一个模板,它描述一类对象的行为和状态,在Java中Object类是所有类的基类(父类)。

(3).对象

对象是类的一个实例(对象不是找个女朋友),有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。

下图中男孩(boy)、女孩(girl)为类(class),而具体的每个人为该类的对象(object):

Javaee期末大族业_开发语言_34


关于类(模板的基本语法)

对于学生我们可以看成是一个类Student,对于学生这个类(模板),我们可以通过属性和方法进行简单的描述,属性描述学生的信息,这个学生叫什么名字,年龄,家庭地址,班级号等,这个类(模板)的属性越多,对应的对象(模板的实例)的信息就越详细,方法描述学生的行为,比如,吃饭,睡觉,喝水,跑步,对应的类的方法越多,相应的对象的就越生动形象。

类的语法结构如下:

public class 类名{
  //属性
  //方法

}

实例如下:

public class Student {
             //属性
	         public String name;
	         public int age;
	         public int classNum;
	         public String address;
	
			//方法(行为)
	        public void eat() {
				System.out.println("吃饭");
			}
	        
	        public void stuInfo() {
				System.out.println(toString());
			}
	        

			public String toString() {
				return "Student [name=" + name + ", age=" + age + ", classNum="
						+ classNum + ", address=" + address + "]";
			}
	            
	        
}

关于什么是匿名类

当我们要去使用某个抽象类/接口的时候我需要做的就是写一个子类来继承该抽象类/实现该接口,然后通过在子类中重写对应的方法,在外部通过实例化该子类,再调用相应的方法,从而实现了对该抽象类/接口的使用,匿名内部类就是不用去写这个抽象类/接口的子类,直接创建该子类,并重写相应的方法,从而实现了对该抽象类/接口的使用。

语法结构如下:

new 父类名或者接口名(){
	//相应的方法重写
}

对象如何创建实例:

  • 对象创建:类名 对象名=new 类名();//无参构造创建对象
  • 对象的创建:类名 对象名=new 类名(参数,参赛...);//有参构造创建对象(类名(参数,参赛…)对应类的构造方法)
  • 方法调用:对象.方法名()
  • 对象属性的访问/赋值:对象.属性名; /对象.属性名=属性值; (这种方式需要注意属性的访问权限,后面会用get,set进行访问和设置)
public class Test {
				public static void main(String[] args) {
					Student admin=new Student();
					admin.name="张三";
					admin.age=10;
					admin.classNum=2;
					admin.address="奈何桥";
					
					//学生信息
					admin.stuInfo();
					
					//执行eat()方法
					admin.eat();
					 
				}
}

运行效果:

Javaee期末大族业_后端_35

关于对象的比较(==和equals()):

对于==

  • 对于基本数据类型,“==”只看两个数据的值是否相等。比如两个int 型的变量,就只看两个变量的值是否相等。
  • 对于引用数据类型,“==”只看两个数据的堆内存地址。比如两个new的User对象,new一次就新分配一个内存空间,因此两个new的User对象堆内存地址值就是不一样的。

对于equals()(从equals源码可知,equals()本质还是在做“==”)

Javaee期末大族业_java_36


代码如下:

int a=10,b=10;
		System.out.println(a==b);//true
		System.out.println(Integer.valueOf(a).equals(b));//true

执行效果:

Javaee期末大族业_后端_37

但是equals()可以进行重写:

Javaee期末大族业_数据类型_38


执行结果:

Javaee期末大族业_后端_39


从上面我们可以看到System.out.println(aString2== bString2);的输出结果为false,而System.out.println(aString== bString);输出的结果为true,因为String aString="测试";这种方式其实就是在常量池中对这个值分配一个地址给它,当String bString="测试"的时候,常量池中已经有了这个"测试"值,就把对应的地址分配给它,所以这样aStringbString的地址其实是一样的,所以返回true,但当创建对象的时候就不是这样了,这种情况是直接在堆内存中开辟了一块新的空间去储存,但是前面说的equals()本质就是==,为什么还是返回false这是因为String这个类重写了Object父类的equals()方法。

Javaee期末大族业_Javaee期末大族业_40


关于重写和重载:

重写:重新写一个将原来方法进行覆盖了,调用的时候调用自己重写的方法
重载:多写一个或多个方法名相同的方法但是形参一定不同(形参的数据类型,形参的长度),返回数据类型可以不同,这样就可以同一个方法有多种加载方式。

//重写Object下的toString()
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", classNum="
				+ classNum + ", address=" + address + "]";
	}
	
	//【1】重载toString()方法
	public String toString(int a) {
		return "Student [name=" + name + ", age=" + age + ", classNum="
				+ classNum + ", address=" + address + "]";
	}
	
	//【3】形参的长度不同
	public String toString(int a,int b) {
		return "Student [name=" + name + ", age=" + age + ", classNum="
				+ classNum + ", address=" + address + "]";
	}
	
	//【4】形参的数据类型不同
	public String toString(String a) {
		return "Student [name=" + name + ", age=" + age + ", classNum="
				+ classNum + ", address=" + address + "]";
	}
	
	//【5】返回数据可以不同
	public void toString(String a,int c) {
		System.out.println( "Student [name=" + name + ", age=" + age + ", classNum="
				+ classNum + ", address=" + address + "]");
	}
(4)三大特性(封装,继承,多态)

封装:

封装(Encapsulation)是面向对象方法的重要原则,就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。

  • 属性私有化,公有访问,通过get(),set()接口进行访问和初始化
  • 有参构造方法初始化对象—>多个参数一起进行初始化(减少访问次数),可创建多个不同形参的构造方法提供多种初始化方案

封装的优点:

  1. 提高代码的安全性。
  2. 提高代码的复用性。
  3. “高内聚”:封装细节,便于修改内部代码,提高可维护性。
  4. “低耦合”:简化外部调用,便于调用者使用,便于扩展和协作

例子(🔺对上面的例子进行封装操作):
Student部分的代码如下:

public class Student {
    //属性
    private String name;
    private int age;
    private int classNum;
    private String address;

    public Student() {
		// TODO Auto-generated constructor stub
	}
    
	public Student(String name, int age, int classNum, String address) {
		this.name = name;
		this.age = age;
		this.classNum = classNum;
		this.address = address;
	}
    
	//方法(行为)
   public void eat() {
		System.out.println("吃饭");
	}
   
   public void stuInfo() {
		System.out.println(toString());
	}
   

	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", classNum="
				+ classNum + ", address=" + address + "]";
	}

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		if (age>0&&age<300) {
			this.age = age;	
		}
		this.age=0;
	}

	public int getClassNum() {
		return classNum;
	}

	public void setClassNum(int classNum) {
		this.classNum = classNum;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	
}

Test部分代码如下:

public class Test {
	public static void main(String[] args) {
		//通过无参构造方法初始化对象
		Student admin=new Student();
		admin.setName("张三");
		admin.setAge(10);
		admin.setClassNum(2);
		admin.setAddress("奈何桥");
		
		//通过有参构造方法初始化对象
		Student admin2=new Student("李四",12,2,"孟婆汤");
		
		//学生信息
		admin.stuInfo();
		
		//执行eat()方法
		admin.eat();
		 
	}
}

执行效果:

Javaee期末大族业_java_41

小白白必看:关于如何自动生成属性的get()set()方法:

Javaee期末大族业_数据类型_42


勾选要具体要生成属性的get()set()方法,选择OK即可生成

Javaee期末大族业_Javaee期末大族业_43


关于如何自动生成有参构造方法:

Javaee期末大族业_开发语言_44


选择要生成的有参构造函数的参数:

Javaee期末大族业_java_45


点击ok自动生成,如下:

Javaee期末大族业_后端_46

注意:

当一个类中有了有参构造函数之后,java机制将不再自动生成无参构造方法。

Javaee期末大族业_java_47

在属性对应的set方法中,可以通过相应的if语句来保证数据的合理性( 不推荐使用

Javaee期末大族业_开发语言_48

继承:

继承(英语:inheritance)是面向对象软件技术中的一个概念。它使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用–(合理使用继承就能大大减少重复代码,提高代码复用性)
Java语言是非常典型的面向对象的语言,在Java语言中继承就是子类继承父类的属性和方法,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类相同的方法。父类有时也叫基类、超类;子类有时也被称为派生类

Javaee期末大族业_后端_49


在没有学习继承之前,我们看见一个对象,就编写一个对象的模板,学生模板,老师模板,警察模板,其实我们可以发现上面这些模板其实有很多相同的属性,方法,这样就让我们写了很多重复代码,为了解决这个问题推出了继承的概论,就上面问题,其实我们可以先写一个人类模板,然后其他模板继承人类模板,人类模板的属性方法就可以继承给它的子类,这样这些相同属性,公用的方法就无需编写。

例子动物的例子(如🔺上图所示):

创建Animal类

class Animal
{
    public int id;
    public String name;
    public int age;
    public int weight;

    public Animal(int id, String name, int age, int weight) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.weight = weight;
    }
    //这里省略get set方法
    public void sayHello()
    {
        System.out.println("hello");
    }
    public void eat()
    {
        System.out.println("I'm eating");
    }
    public void sing()
    {
        System.out.println("sing");
    }
}

子类继承父类的语法:

class 子类 extends 父类{//继承animal

}

注意: 在Java中,类的继承是单一继承,也就是说一个子类只能拥有一个父类,所以extends只能继承一个类。

Javaee期末大族业_后端_50

而Dog,Cat,Chicken类可以这样设计:

class Dog extends Animal//继承animal
{
    public Dog(int id, String name, int age, int weight) {
        super(id, name, age, weight);//调用父类构造方法
    }
}
class Cat extends Animal{

    public Cat(int id, String name, int age, int weight) {
        super(id, name, age, weight);//调用父类构造方法
    }
}
class Chicken extends Animal{

    public Chicken(int id, String name, int age, int weight) {
        super(id, name, age, weight);//调用父类构造方法
    }
    //鸡下蛋
    public void layEggs()
    {
        System.out.println("我是老母鸡下蛋啦,咯哒咯!咯哒咯!");
    }
}

多态(同一个对象在不同的场景下有不同的形态):

一个类具有多个形态,根据对象的不同执行的动作也会不同(方法),比如父类Animal,有二个子类Dog,Cat,二个子类都重写了Animal的eat()方法,当父类指向Dog对象的时候Animal animal= new Dog();,执行的就是Dog的eat()【狗吃骨头】,当父类指向Cat对象的时候Animal animal= new Cat();执行的就是Cat的eat()【猫吃鱼】。

条件:

  • 在子父类中(继承关系),子类重写父类相关的方法
  • 父类引用指向子类对象:Animal animal= new Dog();

代码:

package com.dudu;

public class Animal {
        private String name;
        private int age;

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

    public void eat(){
        System.out.println("吃饭");
    }

    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;
    }

    public static void main(String[] args) {
        Animal animal = new Dog();
        Animal animal2 = new Cat();
        animal.eat();
        animal2.eat();
    }
}



class Dog extends  Animal{
    public Dog() {
        super("小狗",3);
    }

    public Dog(String name, int age) {
        super(name, age);
    }

    public void eat(){
        System.out.println(super.getName()+"吃骨头");
    }
}

class Cat extends  Animal{
    public Cat() {
        super("小猫",4);
    }

    public Cat(String name, int age) {
        super(name, age);
    }

    public void eat(){
        System.out.println(super.getName()+"吃鱼");
    }
}

运行效果:

Javaee期末大族业_Javaee期末大族业_51

该部分相关学习链接:
菜鸟教程多态性

JAVA的多态用几句话能直观的解释一下吗?

关于抽象,接口
抽象:

在Java面向对象当中,所有的对象都是用类进行描绘的,但是并不是所有的类都是用来描绘对象的,如果一个类没有包含足够多的信息来描述一个具体的对象,这样的类就是抽象类。

抽象类的定义方式

abstract class 类名 {

}
  • 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
  • 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
  • 抽象类中,可以有成员变量(全局变量)。
  • 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  • 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译报错。除非该子类也是抽象类。

抽象类与普通类的区别

  • 抽象类使用abstract修饰;普通类没有abstract修饰
  • 抽象类不能实例化;普通类可以实例化
  • 抽象类可以包含抽象方法,也可以包含非抽象方法;普通类不能有抽象方法

关于抽象类是否可实例化问题

抽象方法的定义方式
抽象方法不能用private、final、static、native修饰

public abstract 返回值类型 方法名(参数);

抽象类的特征:

  • 抽象类不能实例化对象,所以抽象类必须被继承才能使用,其他的功能和普通类相同。
  • 一个类只能继承一个抽象类。
  • 抽象类的修饰符不能是private。
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  • 构造方法,类方法(静态方法,被static修饰的方法)不能声明为抽象方法。
  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

接口(对方法进行抽象):

在软件工程中,接口泛指供别人调用的方法。在Java中接口是一个抽象类型,比抽象类更加抽象,是抽象方法的集合。一个类通过继承接口的方式,从而继承接口的抽象方法。从定义上看,接口只是一个集合,并不是类。类描述了属性和方法,而接口只包含方法(未实现的方法)和常量。

接口的语法:

public interface 接口名称 {

//声明常量

//抽象方法

}

接口的变量会被隐式的指定为public static final 变量(并且只能是public static final 变量,用private修饰会编译报错)

🔻(下面的错误是因为a是一个常量,常量必须进行初始化操作!)

Javaee期末大族业_开发语言_52

接口的方法会隐式的指定为public abstract方法

Javaee期末大族业_后端_53


如何使用接口:

语法:

【public】 class 要实现接口的类 implements 接口1,接口2{
   //重新接口中的所有方法
}
  • 注意:如果一个普通类要同时继承一个类和实现接口,应该先继承后实现(在Java中只能继承一个类,但是可以实现多个接口),否则就会语法报错。例如:public class Aextends B implementsC,D E…
  • 实现接口必须重写接口里面的所有方法(接口里面的方法都是抽象方法)

🔺(抽象类和接口被继承/实现,必须重写抽象类/接口中的抽象方法!)

Javaee期末大族业_数据类型_54

Javaee期末大族业_Javaee期末大族业_55

接口的注意事项:

  • 接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。
  • 在抽象类中,可以包含普通方法和抽象方法,但是在接口中,所有的方法必须是抽象的,不能有方法体,比抽象类更加的抽象。接口规定一个类必须做什么而不规定他如何去做。

关于什么是方法体:

Javaee期末大族业_开发语言_56


接口的特征:

  • 接口中只定义抽象方法,这些方法默认都是public abstract的,在方法声明时可以省略这些修饰符。
  • 在接口中定义实例变量,非抽象实例方法以及静态方法都是不允许的,接口中没有构造方法,也不能被实例化。(接口中只有常量和抽象方法)
  • 一个接口不能实现另一个接口,但是可以多继承其他接口。
  • 接口必须通过类来实现它的抽象方法。
  • 如果一个类不能实现完接口中的抽象方法,那么这个类我们应该设计为抽象类。
  • 不允许创建接口的实例(接口不能被实例化),但是允许定义接口类型的引用变量引用实现该接口的类的实例(多态)

🔺(一个接口不能实现另一个接口,但是可以多继承其他接口)

Javaee期末大族业_开发语言_57


Javaee期末大族业_java_58

🔺(不允许创建接口的实例(接口不能被实例化),但是允许定义接口类型的引用变量引用实现该接口的类的实例(多态))

//定义接口InterA
interface InterA
{
 void fun();
}
//实现接口InterA的类B
class B implements InterA
{
 public void fun()
 {
  System.out.println(“This is B”);
 }
}

//实现接口InterA的类C
class C implements InterA
{
 public void fun()
 {
  System.out.println(“This is C”);
 }
}

class Test
{
 public static void main(String[] args)
 {
  InterA a;
  a= new B();
  a.fun();
  a = new C();
  a.fun();
 }
}

输出结果为:
This is B
This is C

🔺通过上面抽象类和接口的学习再看上面讲到的匿名对象应该就能够很清晰的理解了。

Javaee期末大族业_java_59

部分内容来源于
:知乎:Java抽象类和接口(详解)

(4) this关键字,super关键字,static关键字,final关键字

  • this关键字指向当前对象
  • super关键字指向父类对象
  • static关键字指向,可以将数据共享给对象使用,可以通过类名.静态方法/属性进行调用
  • final关键字表示不可修改,修饰属性的时候为不可修改的属性就是常量,当修饰类的时候,该类不可继承,当修饰方法的时候该方法不可重写

Javaee期末大族业_java_60


Javaee期末大族业_开发语言_61

子类对象继承父类的属性和方法:

Javaee期末大族业_数据类型_62


如果父类有有参构造函数,可以通过下面的操作对对象进行初始化操作:

Javaee期末大族业_数据类型_63


(5) 类的常用方法(String;StringBuffer,Calendar)
String类:

(1)字符串的创建

语法1: String =字符串的值; //存储在公共池中
语法2: String 变量名=new String();//存储在堆中

(2)字符串进行拼接:通过+

语法1: 字符串+字符串语法2: 字符串.concat(字符串)

Javaee期末大族业_java_64

运行效果:

Javaee期末大族业_后端_65


(3)字符串不可变

进行拼接操作的字符串会生成新的字符串不会更改以前的值,字符串本质是一个char[]的常量

Javaee期末大族业_Javaee期末大族业_66

代码实例:

Javaee期末大族业_Javaee期末大族业_67


运行效果:

Javaee期末大族业_开发语言_68


(4)字符串常用方法

Javaee期末大族业_Javaee期末大族业_69


Javaee期末大族业_java_70


StringBuffer和StringBuilder类:

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

String、StringBuffer与StringBuilder之间区别

Javaee期末大族业_开发语言_71

  • String

String是一个字符数组 常量

Javaee期末大族业_开发语言_72

  • StringBuffer

StringBuffer保存的是一个字符数组 变量

Javaee期末大族业_Javaee期末大族业_73


Javaee期末大族业_后端_74


Javaee期末大族业_开发语言_75


StringBuffer扩容机制

Javaee期末大族业_开发语言_76


Javaee期末大族业_后端_77


StringBuffer线程安全

Javaee期末大族业_开发语言_78

  • StringBuilder

StringBuilder存放的内容为字符数组 变量

Javaee期末大族业_java_79


Javaee期末大族业_开发语言_80


都是使用AbstractStringBuilder父类进行操作

Javaee期末大族业_开发语言_81

线程不安全(速度更快,适合单线程操作)

Javaee期末大族业_java_82

创建StringBuffer(StringBuilder的创建和相应方法的使用和StringBuffer基本一致):
StringBuffer 对象名= new StringBuffer ();//无参构造

有参构造创建StringBuffer对象参照下图:🔻

Javaee期末大族业_开发语言_83


注意一下:

StringBuilder stringBuilder=new StringBuilder(10);表示创建一个容量为10(0~9)的StringBuilder对象(StringBuffer一样)

Javaee期末大族业_后端_84


StringBuffer的追加,插入,和删除:

  • 当进行插入的时候,插入的对应序号如果有值,将会移到插入内容的末尾(下图insert(8,“Java”))

Javaee期末大族业_Javaee期末大族业_85


StringBuffer常用的方法:

Javaee期末大族业_开发语言_86

Calendar类:菜鸟编程Java 日期时间

12.异常机制

你可以通过我的这篇博文了解这部分的知识:Java基础异常处理

13.集合(Set,List,Map)

数组存放数据时需要先设置存放数据的容量大小,并且在删除数据的时候效率较低,为了更好的对数据进行处理,根据数据结构的不同,线程的安全性等多方面考虑,Java集合Api提供了丰富的集合操作,让我们对数据进行更优的处理。

集合体系:

  • Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等。
  • Java 集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包。

Javaee期末大族业_Javaee期末大族业_87

Set和List的区别

  • Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
  • Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
  • List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变<实现类有ArrayList,LinkedList,Vector> 。

List

List的主要实现:ArrayList, LinkedList, Vector。 ArrayList LinkedList Vector

ArrayList

LinkedList

Vector

底层实现

数组

双向链表

数组

同步性及效率

不同步,非线程安全,效率高,支持随机访问

不同步,非线程安全,效率高

同步,线程安全,效率低

特点

查询快,增删慢

查询慢,增删快

查询快,增删慢

默认容量

10

/

10

扩容机制

int newCapacity = oldCapacity + (oldCapacity >> 1);//1.5 倍

/

2 倍

List常用常用方法:

Javaee期末大族业_Javaee期末大族业_88


实例练习:

public static void main(String[] args) {
		//创建List对象
		List<String> list=new ArrayList<String>();//多态
		//集合初始化
		for (int i = 0; i < 10; i++) {
			list.add("数据:"+i);//数据0,数据1.....数据9
		}
		
		System.out.println("遍历集合:");
		//遍历结合
		for (String str : list) {
			System.out.println(str);
		}
		
		
		System.out.println("获取序号为0的值:");
		//获取集合指定位置的值
		System.out.println(list.get(0));
		System.out.println("获取集合末尾的值:");
		System.out.println(list.get(list.size()-1));//list.size()获取集合的长度
		
		System.out.println("序号为0的值被移除之后,序号0的值变为了:");
		//删除序号为0的值
		list.remove(0);
		//获取序号0的值
		System.out.println(list.get(0));
		
	}

运行效果:

Javaee期末大族业_Javaee期末大族业_89


将上面的ArrayList换成LinkedList运行的结果一致:

  • ArrayList和LinkedList操作方式一致(因为它们都是List接口下的实现类,常用的方法名都是一样的,但是具体的实现方法不一样,这就是多态的妙处)
  • ArrayList和LinkedList虽然操作方式一致但是底层的数据结构是不一致的,一个是数组一个是链表(在使用的时候要根据二者的优缺点进行选择)

Javaee期末大族业_Javaee期末大族业_90


运行效果(结果是一致的):

Javaee期末大族业_数据类型_91


Set

Set的主要实现类:HashSet, TreeSet。

HashSet、TreeSet、LinkedHashSet的区别:

HashSet

TreeSet

LinkedHashSet

底层实现

HashMap

红黑树

LinkedHashMap

重复性

不允许重复

不允许重复

不允许重复

有无序

无序

有序,支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。

时间复杂度

add(),remove(),contains()方法的时间复杂度是O(1)

add(),remove(),contains()方法的时间复杂度是O(logn)

LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet,时间复杂度是 O(1)。

同步性

不同步,线程不安全

不同步,线程不安全

不同步,线程不安全

null值

允许null值

不支持null值,会抛出 java.lang.NullPointerException 异常。因为TreeSet应用 compareTo() 方法于各个元素来比较他们,当比较null值时会抛出 NullPointerException异常。

允许null值

比较

equals()

compareTo()

equals()

Set常用方法:

Javaee期末大族业_开发语言_92

实例练习:

Javaee期末大族业_开发语言_93

运行效果:

  • 0并没有被加入进去,因为Set的数据不能重复
  • Set集合存放数据的顺序是乱序

Javaee期末大族业_数据类型_94

关于HashSet如何检测重复:

Javaee期末大族业_开发语言_95

TreeSet:
实例练习:

public static void main(String[] args) {
		//创建Set集合
		TreeSet<String> set=new TreeSet();
		set.add("数据:0");
		set.add("数据:0");
		set.add("数据:1");
		//初始化数据
		for (int i = 2; i < 10; i++) {
			set.add("数据:"+i);
		}
		System.out.println("使用Iterator集合遍历:");
		//通过Iterator遍历集合
		Iterator<String> iterator=set.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		System.out.println("使用增强for遍历:");
		for (String string : set) {
			System.out.println(set);
		}
		//获取集合第一个元素的值
		System.out.println("获取集合第一个元素的值:"+set.first());
		//获取集合最后一个元素的值
		System.out.println("获取集合最后一个元素的值"+set.last());
		//删除集合第一个元素的值
		System.out.println("删除集合第一个元素的值");
		set.pollFirst();
		//删除集合最后一个元素的值
		System.out.println("删除集合最后一个元素的值");
		set.pollLast();
		
		    //通过Iterator遍历集合
		    iterator=set.iterator();
			while (iterator.hasNext()) {
				System.out.println(iterator.next());
			}
		
	}

运行效果:

  • 使用增强for运行遍历和iterator接口遍历完全不同,增强for只能获取集合中一组的值,不能获取单个值,并且遍历的次数为集合的长度
  • set.first() //获取集合第一个元素的值
  • set.last() //获取集合最后一个元素的值
  • set.pollFirst() //删除集合第一个元素的值
  • set.pollLast()删除集合最后一个元素的值

Javaee期末大族业_java_96


Map

Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
Map 的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap

HashMap、HashTable、TreeMap的区别:

HashMap

HashTable

TreeMap

底层实现

哈希表(数组+链表)

哈希表(数组+链表)

红黑树

同步性

线程不同步

同步

线程不同步

null值

允许 key 和 Vale 是 null,但是只允许一个 key 为 null,且这个元素存放在哈希表 0 角标位置

不允许key、value 是 null

value允许为null。当未实现 Comparator 接口时,key 不可以为null当实现 Comparator 接口时,若未对 null 情况进行判断,则可能抛 NullPointerException 异常。如果针对null情况实现了,可以存入,但是却不能正常使用get()访问,只能通过遍历去访问

hash

使用hash(Object key)扰动函数对 key 的 hashCode 进行扰动后作为 hash 值

直接使用 key 的 hashCode() 返回值作为 hash 值

容量

容量为 2^4 且容量一定是 2^n

默认容量是11,不一定是 2^n

扩容

两倍,且哈希桶的下标使用 &运算代替了取模

2倍+1,取哈希桶下标是直接用模运算

Map常用方法:

Javaee期末大族业_java_97


实例练习:

Javaee期末大族业_数据类型_98


运行效果:

  • Map集合不能直接通过增强for获取,要通过对应的key获取对应的值,或者通过Entry的方式获取。

Javaee期末大族业_Javaee期末大族业_99

Java集合框架总结

14.IO流

你可以通过我的这篇博文了解这部分知识:JavaSE基础篇之-Java 流(Stream)、文件(File)和IO

15.多线程

你可以通过我的这篇博文了解这部分知识:Java基础多线程

🔻下面的内容适合快速入门:

线程的生命周期:

Javaee期末大族业_后端_100


创建一个线程:

  • 通过实现 Runnable 接口;
  • 通过继承 Thread 类本身;
  • 通过 Callable 和 Future 创建线程。【不写实例】

通过实现 Runnable 接口

public class ThreadTest implements Runnable{
	private String name;
	public ThreadTest(String name){
		this.name=name;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 100; i++) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(this.name+"打印:"+i);
		}
	}
	
	
	
	
	public static void main(String[] args) {
		Thread thread1=new Thread(new ThreadTest("线程1"));
		thread1.start();
		
		Thread thread2=new Thread(new ThreadTest("线程2"));
		thread2.start();
	}
}

运行效果:

Javaee期末大族业_后端_101

通过继承 Thread 类本身

Javaee期末大族业_java_102


运行效果:

Javaee期末大族业_数据类型_103

创建线程的三种方式的对比

  • 采用实现 Runnable、Callable 接口的方式创建多线程时,线程类只是实现了 Runnable 接口或 Callable接口,还可以继承其他类。
  • 使用继承 Thread 类的方式创建多线程时,编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread()方法,直接使用 this 即可获得当前线程。

从前面我们创建的线程可以看出运行并不是同步的:

synchronized的使用(同步互斥锁的使用):

Javaee期末大族业_数据类型_104


运行效果:

Javaee期末大族业_数据类型_105

16.网络编程(TCP【重点】;UDP)

什么是TCP
百度百科:

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1] 定义。

TCP的三次握手保证了TCP的连接可靠性

什么是UDP

Internet 协议集支持一个无连接的传输协议,该协议称为用户数据包协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。RFC 768 [1] 描述了 UDP。

TCP编程实例:
JAVA 仿QQ聊天程序(附源码)Java TCP编程实例