Java基础学习

一、Java语言基础

1.变量

1)变量名

命名规则 :

​ 组成:字母 数字 _ $

​ 不能以数字开头,不能是Java中已经使用的定义的名称(关键字和保留字

命名规范:

​ 类名:大驼峰

​ 变量名:小驼峰

​ 常量:所有字母大写

2)声明|定义变量|使用变量

​ 1)类型 变量=初始值;

​ 2)存值: 变量名=值;

​ 取值:变量名 (System.out.println(变量名))

/**
	使用变量,存 取
*/
public class Dome{
    /*程序入口*/
    public static void main(){
        //声明一个整型变量,初始值为100
        int box=100;
        //改变了值   存
        box=200;
        box=0;
        //取出box值
        System.out.println(box);
    }
}

2.类型

1)基本数据类型(简单数据)

​ 整型:字节型(byte)短整型(short)整型(int)长整型(long)

​ 字符型:char

​ 浮点型:单精度 float 双精度 double

​ 布尔型:boolean(true 和 false)

2)引用数据类型(复杂数据)

​ 最少要二个盒子:String 自己定义的类 不含上面的基本数据类型都是复杂数据

自定义引用数据类型:

​ 1)归类 造图纸 模子 根据需求来自己定义类型,不是系统自带

​ 2)编写方式 声明一个类

public class Xxx{
    //声明变量 放到这里  不放到main中->特征和属性
}

如Person类案例

/**
	Person (名字 年龄 性别)
*/
public class Person{
    //属性
    //名字
    String name;
    //年龄
    int age;
    //性别
    String gender;
}

3)类型转换

1.自动类型转换

类型兼容 (大类型盒子 = 小类型值)

**注意:**大类型参与运算符,尽可能提前 ,大数类型置前

2.强制类型转换

小类型盒子 =(小类型)大值;

除boolean类型之外,在java中boolean类型为1位,没有C语言中真即1

**注意:**类型转换的作用范围

3.运算符

3.1算术运算符

1)+(求和、字符串拼接连接符不是追加符) 字符串不可变

2)- (减法 负数)

3)*

4)/(二个整除,整除没有小数点,也不会四舍五入。

​ 两个整数相除,第二个数不能为0

​ 两个非整数相除如 小数,可以为0 ,值 Infinity)

5)% 模 mod 余数

​ 整数取模(5%2 5%-2 -5%2 -5%-2)余数的符号跟被除数一致

6)++ – (前导++ 先自增 后表达式 后导++ 先表达式再自增)

3.2赋值运算符

= 拷贝内容 拷贝值|地址值

int a=5;
int b=a;//a的内容拷贝 赋值一份b ,不是 清空。。。。
Computer comp1 =new Computer();
Computer comp2 = comp1; // comp1的内 一个对象多个引用
3.3扩展运算符

+= -= *= /= %=

1.简化

int num=5;
num=num+2;
//简化
num+=2;

2.优化

char num='a';
num=num+1;//报错char转化为int
//优化
num+=1;//不报错
3.4关系运算符

< >= <= == != instanceof

  • 返回结果为Boolean类型
  • boolean的变量不能用 > < >= <=
3.5逻辑运算符

&& || !(只操作boolean类型)

短路与: 且&& 当前一个表达式的值为F ,整个表达式的结果已经确定为F ,后面表达式为了提升性能不执行。 短路与。

短路或: 或|| 当前一个表达式的值为T ,整个表达式的结果已经确定为T ,后面表达式为了提升性能不执行。 短路或。

3.6三目运算符

boolean ? 值为true取值1:值为false 取值2

二、流程控制

1.控制语句

1.1if

1)单分支

public class IfControl01{
	//程序入口
	public static void main(String [] args){
		//单分支
		//int age=18;
		int age=getNum(0,100);
		if(age>=18){
			System.out.println("你成年了。。。。。");
		}
	}
	
	//随机数字
	public static int getNum(int min,int max){
		return new java.util.Random().nextInt(max-min+1)+min;
	}
}

2)双分支

public class IfControl02{
	public static void main(String [] args){
		int num=10;
		
		boolean flag=EventFlag(num);
		if(flag){
			System.out.println(num+"是偶数");
		}else{
			System.out.println(num+"是奇数");
		}
	}
	//判断奇偶
	public static boolean EventFlag(int num){
		return num%2==0;
	}
}

3)多分支

public class IfControl03{
	public static void main(String [] args){
		//判断月份是春夏秋冬
		//随机生成月份
		int month=getNum(1,12);
		if(month>=3 && month<=5 ){
			System.out.println(month+"春天");
		}else if(modth>5 && month<=8){
			System.out.println(month+"夏天");
		}else if(month>9 && month<=11){
			System.out.println("秋天");
		}else{
			System.out.println("冬天");
		}
		
	}
	public static int getNum(int min,int max){
		return new java.util.Random().nextInt(max-min+1)+min;
	}
}
1.2switch

多分支,且条件为定值,只适用等于等值 定值

月份 星期数 方向

/**
switch(整数定值|字符串){
	case 值1:
		代码1;
	case 值2:
		代码2;
		.......
	default:
}
*/

案例 打印 季节:

/**
月份春夏秋冬
*/
public class Season{
	public static void main(String [] args){
		//随机生成月份
		int month=getNum(1,12);
		month /=3;
		switch(month){
			case 1:
				System.out.println(month+"春天");
				break;
			case 2:
				System.out.println(month+"夏天");
				break;
			case 3:
				System.out.println(month+"秋天");
				break;
			default:
				System.out.println(month+"冬天");
		}
	}
	public static int getNum(int min,int max){
		return new java.util.Random().nextInt(max-min+1)+min;
	}
}

2.循环语句

2.1理解

有规律的重复,不变+可变 多次if演变,有可能执行多次。

2.2四要素

1)初始表达式

2)条件表达式

3)循环体

4)迭代因子

/**
	循环while打印123
*/
public class LoopWhile {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//while循环
		int count=1;//初始表达式
        //条件表达式
		while(count<=3) { 
            //循环体
			System.out.println("数字:"+count);
           // 迭代因子
			count++;
		}
	}
}
2.3循环分类

1)for(能够确定循环次数,推荐使用for)

for(int i=0;i<5;i++) {
			System.out.println("数字:"+i);
		}

2)while(不能确定循环次数,推荐使用while)

//while循环
		int count=1;
		while(count<=3) {
			System.out.println("数字:"+count);
			count++;
		}

3)do…while(至少循环一次)

int num=1;
		do {
			System.out.println("数字:"+num);
			num++;
		}while(num<=3);
2.4死循环

条件永远为true,服务器大大的死循环

int num=0;
		while(true) {
			System.out.println("数字"+num);
		}
2.5停止循环
//break在循环中 终止本层循环
//死循环
		int num=0;
		while(true) {
			System.out.println("数字"+num);
			if(num==90) {
				break;
			}
		}
2.6暂停循环

continue 暂停本次继续下一次

> ```
> for(int i=0;i<5;i++) {
> 			if(i==3) {
> 				continue;
> 			}
> 			System.out.println("数字:"+i);
> 		}
> 
> ```
2.7多层|多重循环

嵌套循环

ublic class LoopFors {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for(int i=0;i<5;i++){
			for(int j=0;j<=i;j++){
				System.out.print((i+1)+"*"+(j+1)+"="+(i+1)*(j+1)+"\t");
			}
			System.out.println();
		}
	}

}

三、类

一、静态(static)

1.理解

1)静态的就是类的

2)是共享的

3)任何的信息,都得有归属

2.静态方法

1)带有static修饰的方法

2)静态方法里面只能使用静态信息,不能直接使用成员信息

/**
	产生随机数
*/
public static int getInt(int min,int max){
    return new java.util.Random().nextInt(max-min+)+min;
}
3.静态属性

1)属性是static修饰,也是类的属性

/**
定义猪类
*/
public class Pig{
    //颜色
    String color;
    //重量
    double weight;
    //数量  静态属性
    static int count;
}

二、常量

1.理解

常量是值:内容一旦确定不可改变 最终的量

只读 只用不改

2.定义

final 类型 常量名=值

注意:规范 全部大写_

fianl int MAX_X;
fianl int MIN_Y;
//定义PI
public class FinalTest{
    public static void main(String [] args){
        final double PI;
        PI=3,14;
        //最终的量不能改变
        //PI=3.5;
    }
}

三、成员信息

1.理解

1)没有static修饰的方法、属性统一称为成员信息

2)必须存在对象,没有对象不能直接使用

3)成员信息可以使用静态

2.成员方法

1)成员方法可以用一切信息,反之静态方法只能使用静态信息

2)成员方法中存在隐式的this,静态方法中没有this

/**
定义人Person类
*/
public class Person{
    //静态方法
    public static void laugh(){
        System.out.println("笑一笑,十年少");
        /**
        静态不能使用成员信息,没有对象不能直接使用成员信息
        eat();
        think;
        */
    }
    //成员方法
    pubic void eat(){
        System.out.println("吃少一点,都长胖了。。。。");
        //成员方法可以使用一切
        laugh();//静态
        think();//成员
    }
    public void think(){
        System.out.println("今天你努力了吗?????");
    }
}

四、构造器(Constructor)

1.理解

1)方法名和类名相同

2)没有返回类型void

3)只能创建对象时使用new调用

2.作用

1)new 才是创建对象,构造器是为new服务,初始化对象信息

/**
Car类
*/
public class Car{
    //品牌
    String name;
    //价格
    double price;
    //构造器
    public Car(){
        System.out.println("初始化对象信息");
        name="宝马";
        price=100.3;
    }
}
3.空构造器

1)当一个类,没有手动编写构造器时,javac编译器会主动加入一个空构造,确保一个类至少有一个构造器。

2)构造器手动加入,系统不会再加其他构造器

4.构造器重载

同一个类,多个构造器 (方法签名不一样,不同:形参类型 个数 顺序 相同:同一个类,方法名)

/**
	构造器重载  User
*/
public class User{
    //构造器
    public User(){
        System.out.println("构造器初始化信息");
    }
    public User(String name){
        System.out.println("构造器初始化信息");
    }
    public User(String name,String pwd){
        System.out.println("构造器初始化信息");
    }
}
5.this

构造器相互调用,首行

1.this调用者
2.this(实参)
   public class User{
    //构造器
    public User(){
        System.out.println("构造器初始化信息");
    }
    public User(String name){
        this();
    }
    public User(String name,String pwd){
        this(name);
        System.out.println("初始化");
    }
}

五、方法

1.理解

解决某个问题的 有名称的 代码块 。 函数。。。。

  • 具备某个功能
  • 方法名: 可以多次使用 调用
  • 多行代码
2.参数

编写方法,方便外界放入数据的,功能方法内使用 。

编写方法使用: 需要形参(就是变量)

调用方法使用: 需要实参(就是数据)

3.返回

编写方法,根据需要 可能需要 返回值return

4.编写方式格式
public static 返回类型|void 方法名(形参列表){
    代码块。。。。。
}

方法编写时与位置无关。调用时确定顺序。。。。 方法不能嵌套。

/**
	写print方法
*/
public class HelloWorld{
	public static void main(String [] args){
        print();//方法调用
	}
    public static void print(){
        //打印HelloWorld
        System.out.println("HelloWorld");
    }
}
5.方法调用

原路返回,从哪里回哪里

6.方法签名

保证此方法一个类中的唯一性 : 方法名+形参组成(类型 个数 顺序) ,与 形参名 返回类型 方法体无关

/**
	方法签名如下:
*/
main(String[])
add(int,int,int)
abs(int)
print(double)
7.方法重载

两同三不同: 一个类中,方法名相同,形参类型 个数 和顺序不同。

方法调用:就近最优原则

/*方法重载*/
System.out.println("abc");
System.out.println(100);
add(int a,int b);
add(double n,double m);
8.方法递归

方法自己调用自己 : 递归头 递归体 递归结束

/*打印整数*/
public class Num{
    /*程序入口*/
    public static void main(String [] args){
        print(5);//给num传入5
    }
    //方法print
    public static void print(int num){
        //打印数字
        System.out.println(num);
        //方法调用
        print(num+1);
    }
}

六、面向对象Object Oriented Programming (总结)

1.理解和案例

面向对象理解: Object Oriented Programming 代码的组织管理 +数据的存储管理

1)造类型:不是能直接使用 定义声明信息,不能直接使用信息

2)用类型:场景 归属 块 构造器 方法

public class Sum{
	//定义成员变量
	String name;
	int age=18;
	//不能直接使用
	//System.out.println(age);
	//静态块
	static{
		System.out.println("静态块就是初始化类信息");
	}
	//构造块
	{
		System.out.println("构造块就是初始化对象信息");
	}
	//构造器
	public Oop(){
		System.out.println("构造块就是初始化对象信息,只能执行一次。。。");
	}
	public Oop(String name){
		this.name=name;
		System.out.println(name);
	}
	
	//成员方法
	public void play(){
		System.out.println("玩的开心。。。。。");
	}
	public void laugh(){
		System.out.println("大声的笑。。。。。");
	}
	public static void main(String [] args){
		Oop p =new Oop();
		new Oop("xiaoxiao");
		
	}
	
}

七、工具类

1.随机数

目标:获得随机的整数

1)java.lang.Math.random() -->[0,1) 随机的小数

2)java.util.Random nextInt(int bound) -->[0,bound) 随机整数

/*
	产生随机整数[0,max]
*/
public class Tool01{
    //程序入口
    public static void main(String [] args){
       int num=getNum(5);
        System.out.println(num);
    })
    pubic static int getNum(int max){
    //工具方法,创建对象
        java.util.Random random=new java.util.Random();
        int num=random.nextInt(max+1);
        return num;
    }
}
/**
	案例:原本是[0,100] 需求是要[5,100]
		拆开变成[0,95] +5==[5,100]
		关系是 min=5 max=100
		[0,max-min]+min
*/
public class Tool02{
    //程序入口点
    public static void main(){
        
        int num=getNum(3,5);
        System.out.pritnln(num);
       //随机小写字母
        char letter=(char)getNum('a','z');
        System.out.println(letter);
    }
    /**
    	随机整数【0,max】
    */
    pubic static int getNum(int max,int min){
    //工具方法,创建对象
        java.util.Random random=new java.util.Random();
        int num=random.nextInt(max-min+1)+min;
        return num;
    }
    
}
2.键盘输入

目标:获取 整数 小数 字符串

java.util.Scanner

整数:nextInt 小数:nextDouble 字符串:next()

/**
	获取键盘输入  整数  小数  字符串
*/
public class Tool03{
    //入口点
    public static void main(String [] args){
        //调用方法键盘输入整数
        int num =getIntFromConsole("请输入你喜欢的数字:")System.out.println(num);
        //调用方法键盘输入小数
        double money=getDoubleFromConsole("请输入你还有多少钱:");
        System.out.println(money);
        //调用方法键盘输入字符串
        String str=getStrFromConsole("请输入你喜欢做什么:");
        System.out.println(str);
    }
    /**
    	键盘输入整数
    */
    public static int getIntFromConsole(String tips){
        //工具方法,创建对象
        java.util.Scanner scan=new java.util.Scanner(System.in);
        System.out.println(tips);
        int num=scan.nextInt();
        return num;
    }
    /**
    	键盘输入小数
    */
    public static double getDoubleFromConsole(String tips){
        //工具方法,创建对象
        java.util.Scanner scan=new java.util.Scanner(System.in);
        System.out.println(tips);
        double num=scan.nextDouble();
        return num;
    }
    /**
    	键盘输入字符串
    */
    public static String getStrFromConsole(String tips){
        //工具方法,创建对象
        java.util.Scanner scan=new java.util.Scanner(System.in);
        System.out.println(tips);
        String str=scan.next();
        return str;
    }
}

四、对象

1.new

1)开辟空间

​ 先父类默认值

​ 再子类默认值

2)初始化

​ =

​ 块–> 静态块 -->构造块

​ 构造器

3)返回地址给引用

2.引用

成员属性:引用对象.属性

成员方法:引用对象.方法

五、三大特性

一、继承(inheritance)

1.理解

继承 inheritance 父类 基类 子类 派生类 单继承。(子类是父类:延续 新增 重写)

extends 实现继承,当一个类没有显示的继承父类,此父类即Object

2.继承链

​ object 父类

parent System String 子类

3.单继承

一个父类可以存在多个子类,一个子类只能有一个父类

/**
父类 F M  子类 A B C
*/
public class F{
    public void play();
}
class M{
    public void play();
}
class A extends F{}   //A继承F
class C extends F{
    M mother;   //一个父亲 一个母亲
}
//错误的继承
class B extends F,M{}
4.super

1)super表示存在继承的子类中,显示查找父类的信息。

2)this:代表调用者自身;super:代表调用者的父亲对象,只能使用不能破坏也看不到地址

3)super.属性:当子类与父类的属性同名,访问父类的属性

4)super.方法():在子类与父类的方法签名相同|重写,访问父类方法。

5)super():在子类的构造器首行,显示调用父类的构造器;任何的构造器默认是调用父类的空构造。

5.extends

1)子类继承父类使用关键字:extends

2)继承父类:延续 新增 重写

public class Father{
    //名字
    String name;
    //年龄
    String age;
    public void eat(){
        System.out.println("吃吃吃。。。");
    }
    public void study(){
        System.out.println("每天进步一点点");
    }
}
//儿子继承父亲
public class Child extends Father{
    //学号
    String num;
    //成绩
    double score;
    //重写
    public void study(){
        System.out.println("每天在进步");
    }
    //新增
    public void coding(){
        System.out.println("天天敲代码。。");
    }
}
//使用子类继承父类
public class FApp{
    public static void main(String[] args){
        Child c=new Child();
        //延续
        c.name="xiaoxiao";
        c.age=18;
        c.eat();
        //新增
        c.num="124554";
        c.coding();
        //重写
        c.study();
    }
}
6.Override重写

1)overload 重载:两同三不同:同一个类方法名相同,形参类型 个数 顺序不同。

3)不重写:属性 静态方法 私有方法 final

2)override 重写:子类中方法签名相同

/**
servlet: doGet doPost方法重写
*/
public class Servlet {
	public Servlet() {
		service();
	}
	public void service() {
		this.doGet();
		this.doPost();
	}
	public void doGet() {
		System.out.println("Servlet doget");
	}
	public void doPost() {
		System.out.println("Servlet doPost");
	}
	
	public static void main(String[] args) {
		new HttpServlet();
		new FtpServlet();
	}
}

class HttpServlet extends Servlet{
	public HttpServlet() {
		super();
	}
	@Override
	public void doGet() {
		System.out.println("HttpServlet doget");
	}
	@Override
	public void doPost() {
		System.out.println("HttpServlet doPost");
	}
	
}

class FtpServlet extends Servlet{
	public FtpServlet() {
		super();
	}
	@Override
	public void doGet() {
		System.out.println("FtpServlet doget");
	}
	@Override
	public void doPost() {
		System.out.println("FtpServlet doPost");
	}
}



7.子类实例化

子类实例化

1)先静态后成员

2)先父类后子类

3)创建对象new()

  • 开辟空间+默认值

  • 初始化

    1. = 存在赋值
    2. 构造块
    3. 构造器
  • 返回值

    存在继承

    1、父亲的空间+默认值; 子类的空间+默认值

    2、父类依次初始化 完毕后;子类的依次初始化

    3、返回地址给引用

4)就近最优:注意方法是否被重写

​ 如果重写找子类

​ 没有重写找父类的方法

public class Parent {
	int a;
	//构造器
	public Parent() {
		test();
	}
	//方法 
	public void test() {
		System.out.println(a);
	}
	public static void main(String [] args) {
		new Child();
	}
}
class Child extends Parent{
	int a;
	int b;
	//构造器
	public Child() {
		this.a=10;
		this.b=20;
	}
	//方法
	/*public void test() {
		System.out.println(a+"-->"+b);
	}*/
}

二、封装(encapsulation)

1.理解

通过访问权限 各司其职 保护数据

封装 encapsulation 保护数据|社会分工 、访问权限。

2.四个访问权限

public 公开的公共的;一览无遗

protected 受保护的(父类子类之间);合法继承

friendly|default:友好的默认的(空着);家庭和睦

private :私有的 自私自利

本类:public protected friendly private

同包其他类:public protected friendly

不同包子类(子对象访问):public protected

不同其他类:public

3.javaBean

存储数据: po jo vo bo

空构造;属性私有化;setter与getter 访问器;重写 equals

toString

public class Person {
	private String name;
	private int age;
	private String gender;
	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 String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (gender == null) {
			if (other.gender != null)
				return false;
		} else if (!gender.equals(other.gender))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]";
	}
	
	
}

4.各司其职

用户登录案例:

分层:

javaBean:

/**
 * javaBean 存储数据
 * 
 * */
public class User {
	//用户名
    private String uname;
    //密码
    private String upwd;
    //构造器
    public User() {
    	
    }
    //getter和setter访问器
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public String getUpwd() {
		return upwd;
	}
	public void setUpwd(String upwd) {
		this.upwd = upwd;
	}
    //重写  equal toString
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (uname == null) {
			if (other.uname != null)
				return false;
		} else if (!uname.equals(other.uname))
			return false;
		if (upwd == null) {
			if (other.upwd != null)
				return false;
		} else if (!upwd.equals(other.upwd))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "User [uname=" + uname + ", upwd=" + upwd + "]";
	}
	
}

dao层

/**
 * 与数据库交互
 * */
public class UserDao {
	//存储模拟数据  
	public User getDao() {
		User user=new User();
		//用户名 xiaoxiao  密码:123456
		user.setUname("xiaoxiao");
		user.setUpwd("123456");
		return user;
	}
}

service层

/**
 * service  登录业务   承上启下
 * */
public class UserService {
	//使用私有的  安全性
	private UserDao serviceDao;
	public UserService(){
		serviceDao=new UserDao();
	}
	//登录
	public boolean UserLogin(User input) {
		//数据库获取数据
		User dbDate=serviceDao.getDao();
		return dbDate.equals(input);
	}
}

web层

/**
 * 用户界面
 * */
public class UserWeb {
	private UserService userSerive;
	public UserWeb() {
		userSerive =new UserService();
	}
	public String inputUser(){
		//从键盘输入用户名和密码
		String uname=MyUtil.getStrFromConsole("请输入用户名:");
		String upwd=MyUtil.getStrFromConsole("请输入密码:");
		User user=new User();
		user.setUname(uname);
		user.setUpwd(upwd);
		//登录 要比较用户名和密码
		boolean success=userSerive.UserLogin(user);
		//返回成功和失败
		return success?"成功":"失败";
	}
}

app模式

public class UserApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		UserWeb userWeb=new UserWeb();
		String result=userWeb.inputUser();
		System.out.println(result);
	}
}
5.封装实现单例

利用封装实现单例 a single instance of class

  • 1、私有的构造器

  • 2、创建一个私有的静态的属性 对象供外部访问

  • 3、提供公共的静态方法 访问该属性

    /**
     * 1.私有构造器
     * 2.创建私有的静态属性,对象供外部访问
     * 3.提供公共静态方法,访问该属性
     * */
    public class Car {
    	//1.创建私有的静态属性,对象供外部访问
    	private static Car car=new Car();
    	//2.私有构造器
    	private Car() {
    		
    	}
    	//提供公共静态方法,访问该属性
    	public static Car car() {
    		return car;
    	}
    }
    
    public class CarApp {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Car car1=Car.car();
    		Car car2=Car.car();
    		System.out.println(car1==car2);
    	}
    }
    

三、多态(polymorphic)

1.理解

编译看类型运行找对象

多态 polymorphism 多种形态,以不变应万变,代码通用性和扩展性。

多态:多种形态,模糊策略,以不变应万变

2.前提

继承 重写 父类的引用=子类对象

public class Car {
	void run() {
		System.out.println("跑起来。。。。。");
	}
	public static void main(String[] args) {
	//多态
		//父类  车    子类 Bmw
		//子类是父类
		Car car=new Bmw();//bmw是车
		Car car2=new BC();//bc是车
		//子类是子类  错误
		//Bmw bmw=new BC();
        car2.run();
        //新增的方法不可用
        //car2.read();
        
        //类型转换
        BC bc=(BC)car2;
        bc.read();
        
}
class Bmw extends Car{
	void  test() {
		System.out.println("测试起来。。。。");
	}
}
class BC extends Car{
	void run() {
		System.out.println("hhhhhh");
	}
	void read() {
		System.out.println("准备好。。。");
	}
}

3.新增

发生多态时,对新增方法不可见

4.类型转换

1)引用指向对象的类型 可转,转换完成后可以使用新增方法

2)转换常出现错误:ClassCastException 类型转换错误

5.instanceof

1)避免ClassCastException 这个异常

2)引用指向的对象类型是 本类型或父类型 子类类型,在一条链上,否则不能使用instanceof。

System.out.println(car instanceof Bmw);

六、字符串

1.理解

字符串为不可改变的量 ,存储在方法区

2.使用

​ 1、推荐省略的形式,避免创建多个对象

  • 2、变量操作运算 ,都会在堆中开辟对象、
  • String msg = “abc”;
  • msg +=“d”;
  • String msg = “abc”+“d”;
  • 常量|字面值,不会在堆中开辟对象
  • 3、推荐使用 访问常量池的地址intern()
  • 一般来说,字符串 使用常量池
  • String msg2 =“abcd”;
3.字符串方法

string 为字符串,存在大量的已经编写的方法

1) equals() 比较内容==比较地址值

​ equalsIgnoreCase(String anotherString) 比较内容可以忽略大小写

2)length() 长度

3)trim() 去除二边的空格

4)replaceAll() 替换

5)indexOf() 查找子串出现的位置

6)substring() 获取子字符串

/**
	字符串方法
*/
public class Tool04{
    //入口点
    public static void main(String [] args){
        //优化的写法
        String msg1="hello world";
        String msg2="hello world";
        String msg3="hello WOrld";
        //1.比较内容equals()
        boolean flag=msg1.equals(msg3);
        System.out.println(flag);//false
        flag=msg1.equalsIgnoreCase(msg3);
        System.out.println(flag);//true
        //2.长度length()
        int len=msg1.length();
        System.out.pritnln(len);//11
        //3.去除二头空格trim()
        msg1=" very good ";
        String anotherMsg=msg1.trim();
        System.out.println(anotherMsg);//very good
        //4.替换 replaceAll
        msg1=" very good ";
        //空格换成*
        anotherMsg=msg1.replaceAll(" ","*");
        System.out.println(anotherMsg);
        //5.找位置 如果没有 返回-1 indexOf()
        msg1="abc123456an";
        int idx=msg1.indexOf("123");
        System.out.println(idx);
        idx=msg1.indexOf("a",2)
        System.out.pritln(idx);
        //6.获取子串 substring()
        String sub=msg1.substring(0,3);//[0,3)
        system.out.println(sub);
        sub=msg1.substring(2);//[0,length())
        System.out.println(sub);
    }
    
}

七、抽象类

一、抽象类(abstract)

1.理解

具体+规范|模子

之前所有的类都是具体类 (方法有方法体,都编写过) 可以直接使用,现在部分方法不写,定义模子(抽象方法)。

2.子类

抽象类一定有子类,没有子类的抽象类没有意义

3.abstract(抽象类)

1)模拟现实,如果一个不想直接实例化,定义为成abstract类。

2)待子类具体实例化:

​ 不能直接new(),待子类实例化

​ 可能包含抽象方法

public abstract class Shape02 {
	void area() {
		System.out.println("算面积。。。");
	}
	//抽象方法
	public  abstract void move();
}
class Rectangle2 extends Shape02{
	void area() {
		System.out.println("长方形面积。。。");
	}
	@Override
	public void move() {
		// TODO Auto-generated method stub
		
	}
	
}
abstract class Square2 extends Shape02{
	public void area() {
		System.out.println("正方形....");
	}
	
}

Test:测试

package com.shsxt.abstr;

public class STest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//Shape shape=new Shape();//不能实例化
		viewShape02(new Rectangle2());
	}
	private static void viewShape02(Shape02 s2) 	{
		// TODO Auto-generated method stub
        //张方形的面积
		s2.area();
		
	}

}

二、接口

1.标准、规范

按标准按规范制作产品(实现类)即可,特殊的抽象类,全是抽象的(除了静态、私有方法),完全规范。

2.格式

1)全局变量

public static final int MAX_VALUE;

2)抽象方法F

public abstract 返回类型|void 方法名(形参列表);
//abstract可以省略
public void read();

3)私有方法

private 返回类型|void 方法名(形参列表){}
//定义
private void read(int a,int b){
    System.out.println("私有方法");
}

4)静态方法

public static 返回类型|void 方法名(形参列表){}
//定义
public static void testUsb() {
		System.out.println("静态方法");
	}

5)默认方法

public default返回类型|void 方法名(形参列表){}
//定义
public default void test() {
		System.out.println("默认方法");
}
3.实现implements

1)子类–>实现类 重写---->实现

public class Disk implements Usb,Connect {

	@Override
	public void read() {
		Usb.testUsb();
		System.out.println("数据读取中"+Usb.MAX_SIZE);
	}

	@Override
	public void write() {
		System.out.println("数据写出中");
	}

	@Override
	public void connect() {
		System.out.println("设备连接");
	}

}

2)单继承:类与类之间

​ 多实现:类与接口之间

​ 多继承:接口与接口

public interface A {

}
interface B{}
interface C extends A,B{	
}
4.空接口

Cloneable 具备可以复制的能力; Serializable: 具备可序列化|持久化的能力。

5.简单工厂
public class CarFactory {
	/**
	 * 简单工厂:创建对象
	 * @param type
	 * @return
	 */
	public static Car product(String type) {
		if(type.equals("qq")) {
			return new Qq();
		}else if(type.equals("infinity")) {
			return new Infinity();
		}else if(type.equals("bmw")) {
			return new Bmw();
		}
		
		return null;
	}
}
6.简单代理
public interface House {
	void angency();
}
//代理角色
class A implements House{
	private House house;
	public A(House house) {
		this.house=house;
	}
	@Override
	public void angency() {
		// TODO Auto-generated method stub
		ready();
		house.angency();
		compat();
		
	}
	private void ready() {
		System.out.println("准备中。。。");
	}
	private void compat() {
		System.out.println("收合同。。。");
	}
	
}
//真实角色
class B implements House{

	@Override
	public void angency() {
		// TODO Auto-generated method stub
		System.out.println("签合同。。");
	}
//	public void pen() {
//		System.out.println("签合同。。");
//	} 
	
}

八、类的高级特性

一、final

1.理解

final 属性 ---->常量

final 方法 ----->不能重写

final 属性 -------->不能继承 最终的

2.格式

public final class 类名{}//没有子类

/**
 * 最终的类
 * @author TW
 *
 */
public final  class F {

}
class P{
	public final void test() {
		System.out.println("p test");
	}
}
class Child extends P{
	/*
	 //不能重写
	public void test() {
		System.out.println("p test");
	}*/
}

二、内部类

1.类中类
public class Inner {
	//静态属性
	//成员属性
	
	//静态内部类
	public static class MyInner{}
	//成员内部类
	public class MyInner2{}
	
	public static void main(String[] args) {
		//静态内部类
		Inner.MyInner myInner = new Inner.MyInner();
		
		//成员内部类
		Inner inner =new Inner();
		Inner.MyInner2 myInner2 =  inner.new MyInner2();
		myInner2 = new Inner().new MyInner2();
	}
}

2.方法中的类
/**
 * 方法中的类 跟局部变量类型
 * @author TW
 *
 */
public class MyInner {

	public static void main(String[] args) {
		int a =0;
		//局部内部类
		class In{}		
		new In();
	}
}
3.匿名内部类对象
new 父类|接口{
    
}
public static void main(String[] args) {
		//匿名内部类 -->重点
		Cal cal =new Cal(){
			public void add() {
				System.out.println("使用一次");
			}	
		};
		cal.add();
		
		//连写.....
		new Cal(){
			public void add() {
				System.out.println("使用一次");
			}	
		}.add();
		
		//任何一个非final类  |接口都可以编写匿名内部类
		Object obj =new Object() {
			public String toString() {
				return "内部类";
			}
		};
		System.out.println(obj);
		
	}

三、Lambda表达式

1.函数式接口

1)Lambda 表达式,简化匿名内部类的使用的。 重点代码的实现 ,不需要关注类名不需要关注方法名,关注的是形参与方法体

2)一个抽象方法,不计算在内私有、静态、default

/**
 * 包含一个抽象方法的接口  函数式接口
 * @author TW
 *
 */
@FunctionalInterface
public interface Cal {
	//抽象方法
	public void add(int a,int b);	
	private void test() {}
	public static void print() {}
}

2.lambda

1)关注: 形参+返回

2)lambda的写法:1.形参 () 2.-> 3.{} 方法体

public interface Tabs {
	void read();
}

public class TabsTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Tabs ta=()->	{System.out.println("hellword");};
		ta.read();
	}
}

3.方法引用 ::

方法引用 ,简化了Lambda,Lambda是简化了匿名内部类。 需要注意: 方法的形参与返回类型 与 函数式接口的抽象方法能够匹配 即可使用。

1)、构造器引用: 类::new

2)、静态方法 : 类:: 方法名

3)、成员方法: 对象类::方法名

public class Fruit {
	public Fruit() {
		
	}
	public Fruit(String type) {
		
	}
}
public class FruitTest {
	//静态方法
	public static Fruit product(String type) {
		return new Fruit();
	}
	//成员方法
	public Fruit productFruit(String type) {
		return null;
		
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Product p2 =  type-> new Fruit();
		//lambda都是对匿名方法的简写
		Product p=new Product() {

			@Override
			public Fruit product(String type) {
				// TODO Auto-generated method stub
				return null;
			}
			
		};
		//简化 类型 
		p=(type)->{return new Fruit();};
		p=type->new Fruit(type);
		
		//lambda 简化  :: 方法引用
		//构造器引用:构造器::new
		p=Fruit::new;
		//静态方法引用:类::方法名
		p=FruitTest::product;
		//成员方法引用:new类::方法名
		p=new FruitTest()::productFruit;
	}
}

四、包装类

1.理解

对基本类型包装成 引用型

基本类型引用类型
intInteger
doubleDouble
charCharacter
booleanBoolean
byteByte
shortShort
longLong
floatFloat
2.装箱

int ----->Integer: valueOf(int i)

//装箱
		int num=5;
		Integer i=Integer.valueOf(num);
		System.out.println(i);
3.拆箱

Integer------->int: intValue()

//拆箱
		Integer n=Integer.valueOf("12345");
		int m=n.intValue();
		System.out.println(m);
4.自动装|拆箱
//自动装箱
		Integer num=5;
		System.out.println(num);
//自动拆箱
		Integer n=5;
		int i=n;
		System.out.println(i);

九、异常(Throwable)

1.理解

Throwable--------->Error||Exception

异常:程序无法正常执行完毕。

异常的文类:运行时|检查时

2.Error

**Error:**这类不需要程序员关注,一般是由虚拟机生成并脱出的

3.Exception(异常)

**1)RuntimeException:**运行时异常,运行期间发生的异常,编译时没有问题

可以通过增强程序的健壮性来处理 if…else

常见的运行时异常:

  • **空指针异常:**NullPointerException :当对象无法正常存在使用,会发生空指针
  • 类型转换异常: ClassCastException -->intansceof
  • 数组下标越界
  • 数组长度负数异常
  • 数学异常 :ArithmeticException
  • 数字转换异常: NumberFormatException

**2)CheckedException:**检查时异常|编译时异常:发生在编译期间

​ 如果不处理,程序无法运行。

4、异常处理

1)throws:异常抛出,抛给上一层处理,当前不处理

2)try…catch 异常捕获

try{
   		可能会出现异常的代码;
   	}catch(NullPointerException e){ //捕获空指针类型的对象,或者多态
   		如果出现这个异常,执行的代码...
   	}catch(FileNotFoundException e){
  		如果出现这个异常,执行的代码...
   	}....
   	 catch(Exception e){
   		任意类型的异常都可以捕获
   	}finally{
   		无论try中是否出现异常,都会执行finally中的代码
  	}
  

try一旦弄到异常,try后面的代码不执行,直接去找对应得catch,如果后面有很多catch,就依次从上到下判断。一个try后面可以跟多个catch,至少一个catch。

如果发现多个catch,捕获异常类型范围要从小到大。

public class Exception04 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			System.out.println("开始。。。。。。。。。。");
			int i=5/0;//数子异常
			String str=null;//空指针异常
			System.out.println(str);
			FileInputStream file=new FileInputStream("F://bin");//文件找不到异常
			
		}catch(ArithmeticException e) {
			//打印出来
			System.out.println("数字异常。。。。");
			e.printStackTrace();
			System.out.println(e.getMessage());
		}catch(NullPointerException e) {
			System.out.println("空指针。。。。");
			e.printStackTrace();
		}catch(FileNotFoundException e) {
			System.out.println("文件找不到。。。。。");
			e.printStackTrace();
		}catch(Exception e) {
			e.printStackTrace();
			System.out.println("异常处理。。。");
		}finally {
			System.out.println("一般资源最好的地方放这里");
		}
		System.out.println("结束。。。。。。。。");
	}
	
}

5.自定义异常

throw 制造异常

前提:异常对象的类型需要继承自Throwable

自定义异常:

  • 直接或者间接的继承自Exception
  • 运行时异常: 继承自RuntimeException
  • 编译时异常: Exception或者某一个编译时异常的子类
/**
	编译时异常:密码要大于等于6位数
*/
public class Exception05 {

	public static void main(String[] args){
		// TODO Auto-generated method stub
		Info in=new Info();
		String name="xiaoxiao";
		String pwd="123";
		in.setUname(name);
		try {
			in.setUpwd(pwd);
		} catch (StringException e) {
			// TODO Auto-generated catch block
			try {
				in.setUpwd("123456");
			} catch (StringException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		System.out.println(in.toString());
	}
	
}
class Info{
	private String uname;
	private String upwd;
	//setter 和 getter 访问器
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public String getUpwd() {
		return upwd;
	}
	public void setUpwd(String upwd) throws StringException {
		if(upwd.length()>=6) {
			this.upwd = upwd;
		}else {
			throw new StringException(upwd+"密码要大于六位");
		}
		
	}
	@Override
	public String toString() {
		return "Info [uname=" + uname + ", upwd=" + upwd + "]";
	}
	
}
//定义编译异常

class StringException extends Exception{
	public StringException() {
		//super();
	}
	public StringException(String mesgg) {
		super(mesgg);
	}
}

/**
	运行异常:密码大于等于6位数
*/
public class Exception06 {

	public static void main(String[] args){
		// TODO Auto-generated method stub
		Info2 in=new Info2();
		String name="xiaoxiao";
		String pwd="123";
		in.setUname(name);
		if(pwd.length()>=6) {
			in.setUpwd(pwd);
		}else {
			in.setUpwd("123456");
		}
		System.out.println(in.toString());
	}
}
class Info2{
	private String uname;
	private String upwd;
	//setter 和 getter 访问器
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public String getUpwd() {
		return upwd;
	}
	public void setUpwd(String upwd){
		if(upwd.length()>=6) {
			this.upwd = upwd;
		}else {
			throw new StringException(upwd+"密码要大于六位");
		}
		
	}
	@Override
	public String toString() {
		return "Info [uname=" + uname + ", upwd=" + upwd + "]";
	}
	
}
//定义运行异常
class StringException extends RuntimeException{
	public StringException() {
		//super();
	}
	public StringException(String mesgg) {
		super(mesgg);
	}
}

十、数组

一、一维数组

1.理解

1)数组:存储多个数据

2)在内存中是一段连续的内存空间

3)相同数据类型数据的有序集合

2.特点
  • 数组是一个容器,是一个引用数据类型,堆中
  • 数组中的所有数据要求数据类型相同
  • 长度一旦确定不可改变
  • 有序 根据序号使用(索引|下标)
3.数组声明

数据类型 [] 数组名;

数据类型:数组所有数据的数据类型

[]------>

数组名:标识符

//定义静态数组初始化
		int [] arr=new int[] {1,2,3,4,5,6,7,8,9,10};
		//定义动态数组初始化
		int [] arr2=new int[10];
4.数组遍历

数组的遍历:依次的拿出数据的中每一个数据操作

1.for普通for循环

2.增强for循环:for…each

  • for(数据类型 变量名 : 数组名|容器名){

  • 变量名 ->代表数组中的从前到后的每一个数据

    }

//增强for
		for(int i:arr) {
			//System.out.println(i);
		}
		System.out.println(Arrays.toString(arr));
		//普通for
		for(int i=0;i<arr.length;i++) {
			//System.out.println(arr[i]);
			
		}
		System.out.println(Arrays.toString(arr));
5.数组常用方法
  • Arrays.toString(数组) 把数组中的内容以字符串的形式返回
  • Arrays.equals(arr1, arr2) 比较两个数组内容是否相等
  • –从索引为0的位置开始
  • static int[] copyOf(int[] original, int newLength) 拷贝,截取,填充的效果
  • –从索引为指定的位置开始
  • static int[] copyOfRange(int[] original, int from, int to) 从原数组的指定位置开始拷贝,拷贝到指定to位置
  • 注:结束位置不包含
  • static void fill(int[] a, int val) 数组中的所有位置,使用val数值填充
  • static void fill(int[] a, int fromIndex, int toIndex, int val)
  • static void sort(int[] a) 对指定的 int 型数组按数字升序进行排序。
  • static int binarySearch(int[] a, int key) 查找数据出现的索引 返回值: -插入点 - 1
  • 使用前提:先升序排序
int[] arr4= {1,2,3,4,5};
		int[] arr= {1,2,3,4,5};
		//把数组的内容以字符串来输出
		System.out.println(Arrays.toString(arr4));
		//比较二个数组相等equals
		System.out.println(Arrays.equals(arr4, arr));
		//数组copyof拷贝长度截取是索引为0开始
		System.out.println(Arrays.toString(Arrays.copyOf(arr, 3)));
		//索引指定位置进行截取
		System.out.println(Arrays.toString(Arrays.copyOfRange(arr, 1, 3)));
		//全填充数据,为10
		Arrays.fill(arr, 10);
		System.out.println(Arrays.toString(arr));
		//截取数来填充
		Arrays.fill(arr4, 1,3, 8);
		System.out.println(Arrays.toString(arr4));
		//进行排序
		Arrays.sort(arr4);
		System.out.println(Arrays.toString(arr4));
		//查找数组的索引
		System.out.println(Arrays.binarySearch(arr4, 3));

二、二维数组

1.理解

二维数组:数组中嵌套数组,数组中还是数组

2.声明和定义

1)声明:

  • 数据类型 变量名;

  • 数据类型[] 数组名; —一维数组的声明

  • 数据类型[][] 数组名; —二维数组

  • 数据类型[] 数组名[];

  • 数据类型 数组名[][];

    2)初始化:

  • 动态初始化: 创建数组对象的时候不赋值,后续赋值

  • 数据类型[][] 数组名 = new 数据类型[一维的长度][二维的长度];

  • 一维的长度:外层数组

  • 二维的长度:内层的每一个小数组

  • 数据类型[][] 数组名 = new 数据类型[一维的长度][];

  • 数组名[0] = 内层数组的创建方式(不可以使用简略写法);

  • 静态初始化:创建数组对象的同时赋值

  • 数据类型[][] 数组名 = new 数据类型[][]{{1,2,3},{2,3},{4}…};

3.数组遍历

数组遍历:循环嵌套

普通for 和 增强for

//普通for
		for(int i=0;i<arr.length;i++) {
			for(int j=0;j<arr[i].length;j++) {
				System.out.println(arr[i][j]);
			}	
		}
		System.out.println(Arrays.deepToString(arr));
		//增强for
		for(int[] i:arr) {
			for(int j:i) {
				System.out.println(j);
			}
		}
		System.out.println(Arrays.deepToString(arr));

十一、集合类

一、容器

1.理解

容器: 存储多个数据

  • 可以根据数据的个数进行自动变长
  • 存储任意类型的数据,只能为引用数据类型
2.Collection(接口)

list :有序可重复

set :无序不可重复

3.ArrayList

底层实现: 可变数组实现,通过数组的拷贝改变数组的长度动态实现可变

**泛型:**强制检查容器中所有数据的数据类型 ->引用数据类型

​ 可以提高程序的安全性和可读性

  • 优点: 做查询效率高

  • 缺点: 做增删效率低,通过数组拷贝

  • 应用: 大量做查询,少量做增删的时候推荐使用ArrayList

  • 扩容:每次扩容原容量的1.5倍(newCapacity = oldCapacity + (oldCapacity >> 1)😉,使用 Arrays.copyOf进行数据的拷贝

    遍历:

  • 普通for循环

  • 增强for循环

  • 迭代器

  • 使用List有的列表迭代器

    public class ListDemo01 {
    	public static void main(String[] args) {
    		//接口多态,list引用只能调用List接口中的内容
    		List list=new ArrayList();
    		List list2=new ArrayList();
    		list.add("哈哈");
    		list.add(9);
    		list.add('a');
    		list.add(false);
    		list.add(null);
    		System.out.println(list);
    		
    		list2.add("3.3");
    		list2.addAll(list);
    		System.out.println(list2);
    		
    		
    		List<String> list3=new ArrayList<String>(); //list3容器中所有的数据都要为字符串
    		List<String> list4=new ArrayList<String>(); //list3容器中所有的数据都要为字符串
    		list3.add("钢铁侠");
    		list3.add("时间规划局");
    		list3.add("变形金刚");
    		list4.addAll(list3);
    		//list3.add(false);
    		System.out.println(list3);
    		//list3.clear();
    		System.out.println(list3.size());
    		System.out.println(list3.isEmpty());
    		
    		System.out.println(list3.contains("钢铁侠"));
    		list3.remove("钢铁侠");
    		System.out.println(list3);
    		System.out.println(list4);
    		
    		list4.retainAll(list3);
    		System.out.println(list3);
    		System.out.println(list4);
    		
    		String[] str = list3.toArray(new String[0]); 		
    		
    		System.out.println(Arrays.toString(str));
    		//list新增对索引进行操作的系列方法
    		list3.add(1, "黑客帝国");
    		System.out.println(list3);
    		
    		list3.set(2, "哈哈哈");
    		System.out.println("黑客帝国第一次出现的索引:"+list3.indexOf("黑客帝国"));;
    		
    		//遍历方式:
    		System.out.println("----------for---------------");
    		for(int i=0;i<=list3.size()-1;i++){
    			System.out.println(list3.get(i));
    		}
    		
    		System.out.println("----------for..each---------------");
    		for(String s:list3){
    			System.out.println(s);
    		}
    		System.out.println("----------Iterator迭代器  Collection接口存在---------------");
    		//1.获取迭代器对象
    		Iterator<String> it=list3.iterator();
    		//2.判断是否有下一个元素
    		while(it.hasNext()){
    			//3.获取下一个元素
    			System.out.println(it.next());
    		}
    		
    		System.out.println("---------列表迭代器  list接口新增---------------");
    		ListIterator it2=list3.listIterator();
    		while(it2.hasNext()){
    			System.out.println(it2.next());
    		}
    		
    		//从后往前迭代,通过列表迭代器
    	}
    }
    
4.Vector向量

与ArrayList像,都是由数组实现内部存储结构

区别:

  • 早起jdk版本提供,后续jdk版本推荐ArrayList代替Vector
  • Vector线程安全,效率较低,ArrayList线程不安全,效率较高,重效率轻安全
  • 扩容:每次扩容原容量的2倍,没有ArrayList节省空间
5.LinkedList(链列表)

底层:双向链表实现

优点:增删效率高

缺点:查询效率低

注意:容器中只能存放引用数据类型的数据 int->3

会发生自动拆装箱,不需要我们手动控制

为所有的基本数据类型提供了对应的包装类型

intInteger
byteByte
shortShort
longLong
doubleDouble
floatFloat
charCharacter
booleanBoolean
6.set集合

Set接口: 无序不可重复

  • List接口: 有序就可重复

  • 都是Collection的子接口,都是存储单个数据值的容器

  • 无序: 存储的顺序和内部真实存放的顺序不同

  • 实现类: HashSet …

    public class SetDemo01 {
    	public static void main(String[] args) {
    		Set set=new HashSet();
    		set.add("haha");
    		set.add("abc");
    		set.add("cd");
    		set.add("a");
    		set.add("hehe");
    		set.add("hehe");
    		set.add("hehe");
    		System.out.println(set);
    	}
    }
    
7.Map

Map 容器接口

  • 存储的每一个数据都是k-v组成

  • k 无序的,不可重复–>Set集合

  • v 无序的,可重复 -->Collection集合

  • key和value之间存在映射关系,根据key获取value

  • 一个key,只能对应一个value,如果想要对应多个,可以把value存在容器中

  • 如果存储的数据的时候,key相同的数据value会覆盖

    Map的遍历方式:

  • 1.keySet() 获取所有的key,返回一个Set集合,然后可以根据key获取value

  • 2.values() 获取所有的value值,返回一个Collection集合

  • 3.entrySet() 返回此映射中包含的映射关系的Set集合

8.HashMap

底层 : hash表实现(数组+链表+红黑树)

实现:

1.存储键值对的数据 key value->在哈希表结构中

2.key获取hashcode()值一个int和整数,根据hash算法进行计算,算出桶的位置

  • hash算法: hashcode()值 % 数组的长度

  • ​ hashcode()值 & 数组的长度-1 ---->数组的长度必须为2的整数幂

    3.先判断对应桶中是否已经存在数据,判断桶中的数据是否与我当前的key相等,使用equals(),如果相等value覆盖,如果不相等,把数据放入链表的最后

  • 对应桶中是否已经存在数据那就直接放入桶中

    如果equals相等,hashcode一定要保证相等,保证相等的数据桶的位置一样,才会比较equals进行去重hashcode相等,equals不一定相等,所以我才要放入桶的时候比较equals()

    • 总结: 如果使用hashMap存储数据,key是自定义的引用的数据类型,一定要重写hashcode()和equals()方法
    • java8:哈希表(数组+链表+红黑树):当桶中的数据超过8个,把结构当前链表结构变为红黑树
    • 初始容量:16
    • 加载因子:0.75 当16*0.75达到临界点12进行扩容
    • 扩容: 扩容位桶的大小

二、Arrays和Collections

1.理解

Arrays(操作数组的工具类)

此类包含用来操作数组(比如排序和搜索)的各种方法

Collections 操作容器的工具类

Collections.方法

方法: 翻转—》revers 随机 ------》shuffle

默认升序 ----》sort 填充-------》fill

2.HashMap理解

HashMap 线程不安全,效率较高,可以存储null值

  • Hashtable 线程安全的哈希表,不能存储null值

    如何处理HashMap线程安全问题:

  • 1.可以使用Hashtable

  • 2.在Collections的提高了一个方法synchronizedMap(Map<K,V> m) 返回一个线程安全的map

  • 3.juc包(高级并发编程包)下ConcurrentHashMap,是一个线程安全的HashMap–推荐,效率高

3.内部比较器

内部比较器(自然排序):实现一个Comparable的接自然排口,重写冲向方法compareTo() 在方法内部定义默认比较规则每次修改,都要修改源代码,硬编码 。

//内部比较器
class Employee implements Comparable<Employee>{
	private String name;
	private int age;
	public Employee(String name,int age) {
		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 "Employee [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee other = (Employee) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public int compareTo(Employee o) {
		// TODO Auto-generated method stub
		if(o.getAge()==this.age) {
			return o.getName().compareTo(this.name);
		}
		return this.age-o.getAge();
	}
	
}


4.外部比较器

**外部比较器(定制排序)😗*实现一个Comparator接口,重写compare(t1,t2) 方法中定义比较规则

		
		//再次排序,按照不同的比较规则
		Collections.sort(list,new CompareTest2());  //Comparator c = new CompareTest2();
		
	}
}

//定义外部比较器
class CompareTest implements Comparator<Student>{

	@Override
	public int compare(Student o1, Student o2) {
		// TODO Auto-generated method stub
		return o2.getAge()- o1.getAge(); //按照年龄升序排序
	}
	
}

class CompareTest2 implements Comparator<Student>{

	@Override
	public int compare(Student o1, Student o2) {
		// TODO Auto-generated method stub
		return (int) (o2.getHeight()- o1.getHeight()); //按照年龄升序排序
	}
	
}

5.匿名内部类

存在一个接口,对接口中的抽象方法进行重写,调用方法体实现功能

**简化实现类:**实现类本身没有自己的作用,只是为了重写抽象方法

6.简化匿名内部类(Lambda)

java8提供了lambda表达式

  • 使用前提:函数式接口
  • 函数式接口: 只有一个必须要重写的抽象方法的接口

检查函数式接口:@FunctionalInterface

  • 语法:
  • ()->{}
  • () :要重写的抽象方法的参数列表
  • -> :lambda符号,箭头符号,箭头函数,具有上下文推到作用
  • {} :定义抽象方法的方法体

十二、IO流

一、IO流

1.理解

传输数据、做输入输出、拷贝、上传下载

不同流:一连串流动的数据,以先入先出的方式流动,管道

作业:传输数据,读入写出,上传下载

2.流的分类

1)按照流向分: 都是大脑为中心,程序为中心

​ 输出流、输入流

​ 文件(数据源)–输入流–>程序(目的地) 程序–输出->文件

2)按照操作数据单元:

​ 字节流:万能流,能够传输任意类型的数据

​ 字符流:纯文本内容

3)按照功能分:

​ 节点流:真实用来传输数据,数据从数据源到目的地

  功能流:扩展节点流的功能	
3.字节流

读入 以程序为中心 数据源–读入–>程序

  • InputStream 抽象父类 字节输入流

  • FileInputStream 文件字节输入流,从系统文件中读入数据到程序

  • 构造器 FileInputStream(String name) 内部会先构建File对象,然后调用下面结构File对象的构造器

  • new FileInputStream(File);

  • 方法

  • read()->返回值int,读到的字节数据,如果没有数据返回-1 读入一个字节的数据

  • read(byte[]) 一个字节数组一个字节数组读入,返回读入到数组中数据的个数,如果没有读到,返回-1。

  • 注意:java中字符串中表示路径可以使用\或者/,使用\会识别成为转义字符

    public class IODemo01 {
    
    	public static void main(String[] args) throws IOException {
    		// TODO Auto-generated method stub
    		//创建一个文件字节流
    		FileInputStream file=new FileInputStream("F:\\test.txt");
    		//System.out.println(file);
    		//读取文件信息一个字节
    //		int num=file.read();
    //		System.out.println((char)num);
    		//用循环来读取每个字节,循环为-1的时候结束
    		int num=-1;
    		while((num=file.read())!=-1){
    			System.out.print((char)num);
    		}
    		//读取文件信息以数组输出
    		byte[] by=new byte[1024];
    		//文件有多少个字节
    		int len=-1;
    		while((len=file.read(by))!=-1){
    			System.out.println(new String(by,0,len));
    		}
    		file.close();
    	}
    }
    

字节输出流:

  • OutputStream 抽象父类

  • FileOutputStream 文件字节输出流

  • 构造器

  • FileOutputStream(String name) 创建一个文件输出流写入文件指定名称。

  • 默认覆盖原有内容

  • FileOutputStream(String name, boolean append)写出 并且追加。

  • 常用方法

  • write(int)

  • write(byte[] b)

  • write(byte[] b, int off, int len)

  • flush() 只要是输出流都要记得关闭之前刷出

  • close()

  • 写出的时候,如果文件系统中不存在,系统会自动帮你创建一个,但是如果是目录不存在,系统不会创建

    public class IODemo02 {
    
    	public static void main(String[] args) throws IOException, InterruptedException {
    		// TODO Auto-generated method stub
    		//文件输出流,追加blooean ture(append)
    		FileOutputStream os=new FileOutputStream("F://test.txt",true);
    		//写入write(int)
    		os.write(97);
    		//write(byte[] b)
    		os.write("hhhh".getBytes());
    		//刷出
    		os.flush();
    		//关闭
    		os.close();
    	}
    }
    
5.文件拷贝字符流

数据源文件----->程序------>目的地文件

  • 文件拷贝:

  • 1.创建流

  • 文件字节输入流

  • 文件字节输出流

  • 2.先读入 后写出

  • 3.刷出

  • 4.关闭(后打开的先关闭)

    public class CopyFile03 {
    	public static void main(String[] args) {
    		//1.创建流
    		InputStream is=null;
    		OutputStream os=null;
    		try {
    			/*is=new FileInputStream("D:/test.txt");
    			os=new FileOutputStream("E:/test.txt");*/
    			//2.先读入 后写出
    			byte[] car=new byte[1024];
    			int len=-1;
    			while(-1!=(len=is.read(car))){
    				os.write(car, 0, len);
    			}
    			//3.刷出
    			os.flush();
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally{ //无论try中是否出现异常代码,都会执行finally中的关闭功能
    			//4.关闭(后打开的先关闭)
    			try {
    				if(os!=null){  //预防空指针异常出现
    					os.close();
    				}
    				if(is!=null){  //预防空指针异常出现
    					is.close();
    				}
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		
    	}
    }
    
    
6.字符流

字符流:

  • 只能拷贝纯文本的数据

  • 输入流: Reader FileReader read() read(char[]) close()

  • 输出流: Writer FileWriter write() + flush() close()

  • 实现字符流的文件拷贝,测试拷贝图片不合适

    public class IODemo03 {
    
    	public static void main(String[] args) throws IOException {
    		// TODO Auto-generated method stub
    		//字符流  Reader Writer
    		//输入流
    		Reader rd=new FileReader("F://test.txt");
    		//Reader rd=new FileReader("D://1.jpg");
    		//写入流
    		//Writer rt=new FileWriter("D://3.jpg");
    		Writer rt=new FileWriter("F://hh.txt");
    		//读写
    		char [] car=new char[1024];
    		int len=-1;
    		while((len=rd.read(car))!=-1){
    			rt.write(car, 0, len);
    		}
    		//刷出
    		rt.flush();
    		//关闭
    		rt.close();
    		rd.close();
    	}
    }
    
7.对象流(功能流)

对象流 (功能流) :读写对象|任意类型数据 保留数据+数据类型

  • 使用: 功能流(节点流)

  • 功能流:提高节点流的功能,增强性能

  • ObjectInputStream 对象|反序列化输入流 新增方法:readXxx()

  • ObjectOutputStream 对象|序列化字节输出流 新增方法:writeXxx()

  • 注意:不能发生多态

  • 序列化:把对象数据转为可存储或者可传输的过程,成为序列化

  • 不是所有的类型都能够序列化 java.io.Serializable

  • 先序列化后反序列化

  • 读写的内容顺序保持一致

  • 不是所有的属性都需要序列化 transient,属性值为默认值

  • 静态的内容不会被序列化

  • 如果父类实现序列化接口,子类的内容也可以序列化,子类实现序列化接口,子类只能序列化子类的内容,父类的内容无法序列化

    public class ObjectDemo01 {
    
    	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
    		// TODO Auto-generated method stub
    		write("F://test.txt");
    		read("F://test.txt");
    	}
    	//序列化输出流   name:目的地文件的路径
    	public static void write(String name) throws FileNotFoundException, IOException{
    		//定义对象流输出流
    		ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream(name));
    		Student s=new Student("xiao",18);
    		//写出
    		os.writeBoolean(true);
    		os.writeUTF("UTF-8");
    		os.writeObject(s);
    		//刷出
    		os.flush();
    		//关闭
    		os.close();
    		s.age=20;
    	}
    	//反序列化输入流
    	public static void read(String name) throws FileNotFoundException, IOException, ClassNotFoundException{
    		ObjectInputStream is=new ObjectInputStream(new FileInputStream(name));
    		//读入
    		boolean b=is.readBoolean();
    		String str=is.readUTF();
    		Object s=is.readObject();
    		System.out.println(b+"--->"+str+"--->"+s);
    		//关闭
    		is.close();
    	}
    
    }
    

二、函数式接口

1.四大函数式接口
**消费性接口 Consumer<T>**  表示接受单个输入参数并且不返回结果的操作。 
 		void  accept(T t)
 		lambda表达式:T什么型都可以,有参数没有返回值
 		public static void get(String str,Consumer<Stirng>con){
 			con.accept(str);
 		}
 		//String
 		get("jlk",t->t.方法());
 		String::equals//类::成员方法
 		//int
 		get(2,t->{System.out.println(t);})
 		System.out::println//对象::成员方法
 		//boolean
 		 
****供给型接口 Supplier<T>   该供应商提供的结果类型** 
		T	  get()** 
		get()方法在list集合中使用
		public static List<Integer> get(int num,Supplier<List<Integer>>sup){
			List ls=new ArrayList();
			for(int i=0;i<num;i++){
				ls.add(sup.get());
			}
		return list;
		}
		//get(1,()->(int)Math.random()*(5-2+1)+2);
		 //
****函数型接口 Function<T,R> 表示接受一个参数并产生结果的函数。**
		R	  apply(T t)**
		public static String get(String s1,Function<String,String>fun){
		return fun.apply(s2);;
	}
	get("jkk",t->t.方法)
	String::trim//类名::成员方法
****断定型接口 Predicate<T>  表示一个参数的谓词(布尔值函数)。**                      boolean test(T t)**
		public static boolean get(String s,Predicate<String>pre){
			return pre.test(s);
		}
		get("",t->t.方法())
		String::equals   //类名::成员方法
2.方法引用::
  • 简化Lambda表达式,可以理解为Lambda表达式的另一种表现形式

  • 前提: 当重写的抽象方法方法体的实现,其实就是通过调用另外一个已有的方法进行实现,可以通过方法引用进行调用,简化Lambda的写法

  • 对象的引用 ::成员方法;

  • 类名::静态方法名;

  • 类名::成员方法;

  • 要求: 函数型接口的抽象方法的参数列表和返回值要求与内部引用的方法的参数列表和返回值保持一致!!!

    构造器引用:

  • new Person();

  • Person::new;

  • 类型::new;

    /**
     * 对象的引用 ::成员方法;
     * */
    public class Dome01 {
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Fruit f=new Fruit();
    		A<Fruit> a=()->{f.getName();};
    		//对象调用了getName()
    		a=f::getName;
    		//System.out.println();
    	}
    }
    class Fruit{
    	private String name;
    	public Fruit(){
    		
    	}
    	public  void getName(){
    		System.out.println("名字是:"+this.name);
    	}
    }
    //创建接口
    interface A<T>{
    	void get();
    }
    
    
    /**
     * 类名::静态方法名;
     * */
    public class Demo02 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		B<Integer> b=(t)->{Animal.getAge(t);};
    		b=Animal::getAge;
    	}
    }
    class Animal{
    	int age;
    	public Animal(){
    		
    	}
    	public static void getAge(int age){
    		System.out.println("年龄:"+age);
    	}
    }
    interface B<T>{
    	void get(T t);
    }
    
    /**
     * 构造器
     * 类型类名::new;
     * */
    public class Demo03 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Car car=new Car();
    		C<Car> c=()->{return new Car();};
    		c=()->new Car();
    		c=Car::new;
    	}
    
    }
    class Car{
    	String name="str";
    	public Car(){
    		
    	}
    	
    }
    interface C<T>{
    	T get();
    }
    
    
    //类名::静态方法
    public class Demo04 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Student s=new Student();
    		D<Student,String> d=(t)->{return t.get(s);};
    		d=Student::get;
    	}
    
    }
    class Student{
    	String name;
    	public Student(){
    		
    	}
    	public static String get(Student s){
    		return s.name;
    		
    	}
    }
    interface D<T,R>{
    	R get(T t);
    }
    

十三、线程

1.理解

1)多任务多条路径多个顺序流同时执行就是多线程

2)学习多线程的目标:

  • 1.线程的创建 ***

  • 2.线程的状态 **

  • 3.线程安全 ***

    3)线程优点:提高效率,同时执行

    ​ 缺点:复杂

2.多线程的创建方式

1.继承Thread类,重写run()方法,run方法中定义多线程的线程体

/**
 * 继承Thread重写run(),定义多线程
 * */
public class ThreadDemo01 extends Thread{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<10;i++){
			System.out.println("kkh");
			try {
				Thread.sleep(5);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//创建线程
		ThreadDemo01 th=new ThreadDemo01();
		//开启
		th.start();
		for(int i=0;i<10;i++){
			try {
				Thread.sleep(5);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("hhhhhh");
		}

	}
}

2.实现Runnable接口,重写run()方法

  • 推荐:

  • ​ 1.避免单继承的局限性

  • ​ 2.实现资源共享

    public class ThreadDemo02 implements Runnable{
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		//创建线程
    		Thread th=new Thread(new ThreadDemo02());
    		th.start();
    		for(int i=1;i<=100;i++){
    			System.out.println("吃吃");
    			try {
    				//当前线程睡眠指定的时间
    				Thread.sleep(5);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		for(int i=1;i<=100;i++){
    			System.out.println("睡睡");
    			try {
    				//当前线程睡眠指定的时间
    				Thread.sleep(5);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    }
    

    3.实现Callable接口,重写call方法

3.买票模拟多线程
/*
 * 简单模拟12306例子
 * 	100张票,想要让3个人同时买完这100张票
 *  资源共享:共享资源100张票
 */
public class ThreadDemo03 implements Runnable{
	int tickets=100;
	// A B C
	@Override
	public void run() {
		while(true){
			//停止循环的条件
			synchronized (ThreadDemo03.class) {
				if(tickets<=0){
					break;
				}
				try {
					Thread.sleep(2);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"正在购买第"+tickets-- +"张票..");
			}
			
		}
	}
	
	public static void main(String[] args) {
		ThreadDemo03 demo=new ThreadDemo03(); //内存空间中只有100张
		//线程的创建
		Thread th1=new Thread(demo,"猪八戒");
		Thread th2=new Thread(demo,"盾山");
		Thread th3=new Thread(demo,"亚瑟");
		//线程的开启
		th1.start();
		th2.start();
		th3.start();
	}

}

//重写方法异常抛出问题:子类重写的方法<=父类方法上异常抛出类型
interface A{
	void test() throws Exception;
}
class B implements A{

	@Override
	public void test() throws NullPointerException{
		// TODO Auto-generated method stub
		
	}
	
}
4.线程状态

线程状态:

  • 新生状态:new创建一个线程的时候

  • 就绪状态:start(),线程会进入就绪队列,等待cpu的调度

  • 运行状态:cpu调用分配时间片给线程,线程就会运行

  • 阻塞状态:sleep()…

  • 终止状态:线程结束了

  • 一个线程一旦就如到阻塞状态,阻塞解除之后,不会马上恢复到运行,会恢复到就绪状态,再次等待cpu的调度

  • 一个线程一旦进入终止状态,再也不会恢复

    如何一个线程进入就绪状态:

  • 1.start()

  • 2.阻塞解除

  • 3.线程切换,被切换的线程会恢复就绪状态

  • 3.yield() 礼让线程

    进入阻塞状态的方式:

  • 1.sleep

  • 2.wait

  • 3.join

    如何控制一个线程终止:

  • 1.stop…不推荐 2.通过表示判断 3.正常执行结束

  • sleep(): 线程睡眠

  • 1)模拟网络延迟

  • 2)放大问题的可能性

  • 让出cpu的资源,不会让出对象的锁(保证资源睡觉),指定休息多少毫秒

  • yield():礼让线程

  • 让出cpu的资源,恢复到就绪状态

  • join():插队线程

5.方法获取线程状态

Thread中 getState() 获取某个线程的状态

  • 线程优先级:
  • 提高先执行的概率
  • getPriority() 返回该线程的优先级。
  • setPriority(int newPriority)改变这个线程的优先级。
  • 1~10 1最小 10最大 默认是5
6.线程安全

线程安全:

​ 多线程同时操作同一份资源才有可能会出现线程不安全的问题,需要控制安全

  • 同步锁: synchronized

  • 同步方法 : 在方法上使用synchronized修饰

    ​ 成员方法,相当于锁this,代码范围为方法

    ​ 静态方法,相当于锁类(类的class对象),代码范围为方法

    为了让线程排队执行{}中的代码

  • 同步块 synchronized(锁的内容){同步的代码范围}

  • 锁的内容: this 类.class 资源(成员变量)

  • 类.class 相当于把这个类,类的所有内容锁住了,类的所有对象都锁住

  • this 当前调用成员方法的对象,相当于把这个对象的所有资源都锁住了,可以只锁资源

  • 资源: 成员变量,一定要是自定义的引用数据类型的对象

  • 锁的范围:{}->中代码的范围

    注意:

  • 锁的范围太大,效率低

  • 锁的范围太小,锁不住

  • 锁不变的内容

    // 人车共用一个街道:
    //  	street 街道   信号灯boolean 
     //  	人 ns -->true
     //  	车 we -->false
    public class StreetDemo03 {
    	public static void main(String[] args) {
    		Street s=new Street();
    		//人车共用街道
    		new Thread(new Person(s)).start();
    		new Thread(new Car(s)).start();
    	}
    }
    
    //街道类  信号灯   true->ns()		false->we()
    class Street{
    	boolean flag= false;  //信号灯
    	
    	//南北走向
    	public synchronized void ns(){
    		if(flag==false){
    			try {
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}else{
    			try {
    				Thread.sleep(200);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println("人走....");
    			flag=false;
    			this.notify();
    		}
    	}
    	
    	//东西走向
    	public synchronized void we(){
    		if(flag==true){
    			try {
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}else{
    			try {
    				Thread.sleep(200);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			System.out.println("车走....");
    			flag=true;
    			this.notify();
    		}
    	}
    }
    
    class Person implements Runnable{
    	Street street=null;
    	
    	public Person(Street street) {
    		this.street=street;
    	}
    	
    	@Override
    	public void run() {
    		while(true){
    			street.ns();
    		}
    	}
    	 
    
7.两个多线程打印:12A34B56C…
public class StringDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		S s=new S();
		new Thread(new Num(s)).start();
		new Thread(new Cstr(s)).start();
		
	}
}
class S{
	int num=1;
	char c='A';
	boolean flag=false;
	//打印数字二个
	public synchronized void getNum(){
		if(flag==true){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(num+++""+num++);
			
			this.notify();
			flag=true;
		}	
	}
	//打印单个字符
	public synchronized void getChar(){
		if(flag==false){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else{
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(c++);
			this.notify();
			flag=false;
		}	
	}
}
class Cstr implements Runnable{
	S s=null;
	public Cstr(S s){
		this.s=s;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			s.getChar();
			if(s.c>'Z'){
				break;
			}
		}
	}	
	
}
class Num implements Runnable{
	S s=null;
	public Num(S s){
		this.s=s;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			s.getNum();
			if(s.num>52){
				break;
			}
		}
	}
}

十四、网络编程

1.IP
IP:定位网络上的节点(电脑,手机,服务器,路由器...)  InetAddress
 * 	IP分类:
 * 		ipv4  32* 		ipv6  128* 	特殊的IP:
 * 		非注册ip:供组织内部使用  192.168.0.0~192.168.255.255
 * 		本地ip: 127.0.0.1
 * 	ip->域名:DNS服务器进行转换
2.端口

端口: 区分软件 InetSocketAddress

  • 0~65535之间的整数,2个字节
  • 自定义端口号推荐使用它8000以上
  • 统一协议下端口号不能冲突
  • 8000以内的预留端口号
  • 80 : http
  • 8080 : tomcat
  • 3306 : mysql
  • 1521 : oracle
3.传输层协议

标准,规范,协议

udp : 非面向连接 协议简单,开销小,不安全 大小有限制

tcp : 基于连接 3次握手 协议复杂,开销大,效率低 安全 大小没有限制

udp对socket实现

DatagramPacket: 打包|数据报包

DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) 构造一个数据报包发送数据包的长度 length抵消 ioffsetto指定主机上的指定端口号。

DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket length接收数据包的长度。

DatagramSocket : 定义发送端或者接收端

DatagramSocket(int port) 构造一个数据报套接字绑定到本地主机上的指定端口。
DatagramSocket(int port, InetAddress laddr) 创建数据报套接字,绑定到指定的本地地址。

udp基本流程:发送端

1.定义发送端DatagramSocket(int port)

2.准据数据

3.打包

4.发送void send(DatagramPacket p) 从这个套接字发送一个数据报包。

5.关闭

public class UDPSend02{
	public static void main(String[] args) throws IOException {
		System.out.println("-------------发送端----------------");
		//1.定义发送端DatagramSocket(int port)
		DatagramSocket client=new DatagramSocket(6666);
		//2.准据数据
		byte[] arr="海贼王-->香克斯".getBytes();
		//3.打包
		DatagramPacket packet=new DatagramPacket(arr, 0, arr.length,new InetSocketAddress("localhost",9999));
		//4.发送
		client.send(packet);
		//5.关闭
		client.close();
	}
}

udp基本流程:接收端

1.定义接收端 DatagramSocket(int port)

2.打包用来接收数据

3.接收数据 receive(DatagramPacket p) 从这个套接字接收数据报包。

4.处理数据 byte[] getData() int getLength()

5.关闭

public class UDPReceive03 {
	public static void main(String[] args) throws IOException {
		System.out.println("-------------接收端----------------");
		//1.定义接收端 DatagramSocket(int port)
		DatagramSocket server=new DatagramSocket(9999);
		//2.打包用来接收数据
		byte[] arr=new byte[1024*60];
		DatagramPacket packet=new DatagramPacket(arr, arr.length);
		//3.接收数据  receive(DatagramPacket p) 从这个套接字接收数据报包。 
		server.receive(packet);
		//4.处理数据
		byte[] data=packet.getData();
		int len=packet.getLength();
		System.out.println(new String(data,0,len));
		System.out.println(data.length);
		System.out.println(len);
		//5.关闭
		server.close();
	}
}

tcp基本流程:客户端

1.定义客户端 Socket Socket(InetAddress address, int port) 创建一个流套接字连接到指定的端口号在指定的IP地址。

2.io操作 InputStream getInputStream() 返回此套接字的输入流。

3.关闭

public class TcpClient04 {
	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("------我是客户端-------");
		//1.定义客户端
		Socket client=new Socket("127.0.0.1",9999);
		//2.IO操作
		OutputStream os=client.getOutputStream();
		os.write("今天是星期六".getBytes());
		//3.刷出
		os.flush();
		//4.关闭
		os.close();
		client.close();
	}
}

tcp基本流程:服务端

  • 1.定义服务端 ServerSocket(int port) 创建一个服务器套接字绑定到指定端口。

  • 2.阻塞式监听 accept()

  • 3.io操作

  • 4.数据的处理

  • 5.关闭

    public class TcpServer05 {
    	public static void main(String[] args) throws IOException {
    		System.out.println("------我是服务端-------");
    		//1.定义服务端  ServerSocket(int port) 创建一个服务器套接字绑定到指定端口。
    		ServerSocket server=new ServerSocket(9999);
    		//2.阻塞式监听 accept() 
    		Socket socket=server.accept(); 
    		System.out.println("一个客户端连接成功了.....");
    		//3.io操作
    		InputStream is=socket.getInputStream();
    		byte[] arr=new byte[1024];
    		int len=is.read(arr);
    		//4.数据的处理
    		System.out.println(new String(arr,0,len));
    		//5.关闭
    		is.close();
    		socket.close();
    		server.close();
    	}
    }
    
    
4.url

url: 统一资源定位符

  • 互联网的三大基石: html http url

  • URL 类 :

  • https://www.shsxt.com:80/teacher.html

  • 协议:String getProtocol()

  • 域名: String getHost()

  • 端口:int getPort()

  • 资源:

    String getPath()
    ​ 得到这个 URL路径的一部分。
    ​ String getHost()
    ​ 这个 URL的主机名,如果适用的话。
    ​ int getPort()
    ​ 这个 URL的端口号。
    ​ String getProtocol()
    ​ 这个 URL的协议名称。
    ​ String getQuery()
    ​ 获取查询 URL的一部分。
    ​ String getRef()
    ​ 得到了锚(也称为“参考”) URL

    public class Demo01 {
    	public static void main(String[] args) throws IOException {
    		URL url=new URL("https://www.taobao.com");
    		System.out.println(url);
    		System.out.println("协议"+url.getProtocol());
    		System.out.println("端口"+url.getPort());
    		System.out.println("域名"+url.getHost());
    		System.out.println("查询内容"+url.getQuery());
    		System.out.println("锚点"+url.getRef());
    		//获取一个从url位置到程序的输入流
    		InputStream str=url.openStream();
    		//读取
    		byte[] car=new byte[1024];
    		int len=-1;
    		while((len=str.read(car))!=-1){
    			System.out.println(new String(car,0,len));
    		}
    	}
    }
    

十五、反射

1.理解

反射发生在程序运行期间的行为 动态机制

Java反射机制,可以实现以下功能:
①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理。

Class类:代表一个类,位于java.lang包下。

Field类:代表类的成员变量(成员变量也称为类的属性)。

Method类:代表类的方法。

Constructor类:代表类的构造方法。

Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

反射的源头: 一个类型的class对象

如果能够获取一个类的class对象,可以对它进行任何操作

如何获取反射的源头|Class对象呢

  • 反射的对象独一份的,在反射包下

  • 1.对象.getClass()

  • 2.类名.class();

  • 3.Class.forName(报名+类名)

    Person obj=(Person)Class.forName(o).newInstance();
    		obj.sleep();
    		
    		System.out.println("".getClass());
    		System.out.println(String.class=="".getClass());
    		
    		Class cls=Class.forName("java.lang.String");
    		
    		System.out.println(cls.getName());
    		System.out.println(cls.getSimpleName());
    		System.out.println(cls.getModifiers());
    		System.out.println(Modifier.toString(cls.getModifiers()));
    		System.out.println(int.class.isPrimitive());
    	}
    } 
    
    
    class Person{
    	void sleep(){
    		System.out.println("睡觉");
    	}
    }
    class Student extends Person{
    	void sleep(){
    		System.out.println("边上课边睡觉");
    	}
    }
    class Teacher extends Person{
    	void sleep(){
    		System.out.println("边讲课边睡觉");
    	}
    }
    
    
2.操作构造器|操作方法

1)获取构造器

  • Constructor getConstructor(Class<?>... parameterTypes) Constructor<?>[] getConstructors()
		以上只能获取公共的构造器
		Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
		Constructor<?>[] getDeclaredConstructors()  


​ 以上两个获取所有修饰符修饰的

2)指定使用这个构造器在创建对象的时候为对象初始化信息

直接通过Class类中的newInstance() 方法创建调用,默认调用空构造

通过Constructor的newInstance() 创建对象,执行使用当前构造器对对象初始化信息

2) 操作方法

  • 获取方法四个

    获取方法四个:
    ​ getDeclaredMethod(String name, 类<?>... parameterTypes) ​ 返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。 ​ getDeclaredMethods() ​ 返回包含一个数组 方法对象反射的类或接口的所有声明的方法, ​ 通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。 ​ getEnclosingMethod() ​ 如果此类对象表示方法中的本地或匿名类,则返回表示基础类的即时封闭方法的方法对象。 ​ getMethod(String name, 类<?>… parameterTypes)
    ​ 返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。
    ​ getMethods()
    ​ 返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,
    ​ 包括那些由类或接口和那些从超类和超接口继承的声明。

  • 操作方法 Object invoke(Object obj, Object… args) 执行这个方法 第一个参数匹配调用方法的对象,如果是静态方法设置为null 第二个参数:实参

    操作属性**

  • 获取属性四个 getFields()…

  • 操作属性方法: void set(Object obj, Object value) 为某一个属性设置值 第一个参数对象这个成员变量的对象 第二个参数:属性的值

  • get(Object obj) 获取某一个对象的当前属性值

    public static void main(String[] args) throws Exception {
    //		testConstructor(User.class);
    		testField(User.class);
    	}
    
    	//测试反射操作属性(变量)
    	public static void testField(Class<User> cls) throws Exception{
    		//创建一个User对象
    		User user=cls.newInstance();
    		Field field=cls.getDeclaredField("pwd");
    		field.setAccessible(true);
    		field.set(user, 123);
    		System.out.println(user);
    		System.out.println(field.get(user));
    		field.setAccessible(false);
    	}
    	
    	//测试操作构造器
    	public static void testConstructor(Class cls) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
    		Constructor[] cons=cls.getConstructors();
    		System.out.println(Arrays.toString(cons));
    		//1.创建对象指定使用某个构造器
    		Object obj=cons[1].newInstance();
    		System.out.println(obj);
    		
    		//2.通过使用私有构造器
    		Constructor con=cls.getDeclaredConstructor(String.class);
    		//放开构造器的权限  
    		con.setAccessible(true); //打开权限
    		User user=(User)con.newInstance("zhangsan");
    		con.setAccessible(false); //关闭权限
    		System.out.println(user);
    		
    		//3.直接通过class对象创建对象,默认调用共构造
    		User user2=(User)cls.newInstance();
    		System.out.println(user2);
    	}
    }
    
    class User{
    	private String name;
    	private int pwd;
    	
    	public User() {
    		// TODO Auto-generated constructor stub
    	}
    
    	private User(String name) {
    		this.name = name;
    	}
    	
    	public User(String name, int pwd) {
    		super();
    		this.name = name;
    		this.pwd = pwd;
    	}
    
    	@Override
    	public String toString() {
    		return "User [name=" + name + ", pwd=" + pwd + "]";
    	}
    	
    }
    
    
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值