接口

接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来。

interface 接口名{//属性//方法(1. 抽象方法 2.默认实现方法 3.静态方法)
}class 类名 implements 接口{//自己属性//自己方法//必须实现的接口的抽象方法
}

小结:

1.在jdk7.0前 接口里的所有方法都没有方法体

2.jdk8.0后接口类可以有静态方法、默认方法,也就是接口中可以有方法的具体实现

public interface AInterface {//写属性public int n1 = 10;//写方法//在接口中,抽象方法,可以省略abstract关键字public void hi();//jdk8后,可以有默认实现方法,需要使用default关键字修饰default public void ok {System.out.println("ok....");}//在jdk8后,可以有静态方法public static void cry() {System.out.println("cry...");}
}

注意:

1)接口不能被实例化

2)接口中的方法是public方法,接口中抽象可以不用abstract修饰

void aaa()实际上是abstract void aa();

void add() {} 是错误的,抽象方法不可以有方法体

3)一个普通类实现接口,就必须将该接口的所有方法都实现。

4)抽象类实现接口,可以不用实现接口的方法。

5)一个类可以同时实现多个接口

interface IB {}interface IC {}class Pig implements IB,IC {}

6)接口中的属性,只能是final的,而且是public static final 修饰

比如:int a = 1;实际上是public static final int a = 1;(必须初始化)

7)接口中属性的访问形式:接口名.属性名

8)一个接口不能继承其他类,但是可以继承多个接口

interface A extends B,C{ }

9)接口的修饰符 只能是public和默认,和类的修饰符一样

继承 vs 接口

interface Fishable{void swimming();
}interface Birdable{void flying();
}//子类继承父类,拥有父类的功能。
//如果子类需要扩展功能,可以通过实现接口的方式扩展。class LittleMonkey extends Monkey implements Fishable, Birdable{public LittleMonkey(String name) {super(name);}void swimming();void flying();
}

接口和继承解决的问题不同

继承的价值之要在于:解决代码的复用性和可维护性

接口的价值:设计,设计好各种规范,让其他类去实现这些方法,更加灵活。

接口在一定程度上实现代码的解耦

接口的多态特性

1)多态参数(接口引用可以指向实现了接口的类的对象)

Usb usb 既可以接受手机对象,也可以接受相机对象

public class Computer {public void work(UsbInterface usbInterface) {usbInterface.start();usbInterface.stop(); //动态绑定}
}
public class no1 {public static void main(String[] args) {//接口的多态体现//接口类型的变量 if01可以指向实现了IF接口的对象实例IF if01 = new Monster();if01 = new Car();}
}interface IF{}
class Monster implements IF{}
class Car implements IF{}

2)多态数组

public class no1 {public static void main(String[] args) {Usb[] usbs = new Usb[2];usbs[0] = new Phone();usbs[1] = new Camera();}
}interface Usb{}
class Phone implements Usb{}
class Camera implements Usb{}
public class no1 {public static void main(String[] args) {Usb[] usbs = new Usb[2];usbs[0] = new Phone();usbs[1] = new Camera();for(int i = 0; i < usbs.length; i++) {usb[i].work(); //动态绑定if(usb[i] if (usbs instanceof Phone) {((Phone) usb[i)).call(); //向下转型调用特殊方法}}
}interface Usb{void work() {}
}
class Phone implements Usb{public void work() {}
}
class Camera implements Usb{@Overridepublic void work() {// TODO Auto-generated method stub}
}
public class no1{public static void main(String[] args) {IG ig = new Teacher();IH ih = new Teacher();//如果IG继承了IH接口,而Teacher实现了IG接口//那么实际上,Teacher也实现了IH接口}
}interface IH {}
interface IG extends IH{}
class Teacher implements IG{}
interface A{int x = 0;
}class B {int x = 1;
}class C extends B implements A {public void pX() {//若输出x不明确//可以明确指定x//访问接口的x 就使用A.x//访问父类的x 就使用super.xSystem.out.println(A.x + " " + super.x);}
}

例:


内部类

基本介绍:一个类的内部又完整嵌套了另一个类结构,被嵌套的类成为内部类(inner class)

嵌套其他类的类成为外部类(outer class)

内部类的最大特点是:可以直接访问私有属性,并且可以体现类与类之间的包含关系

类的五大成员:属性、方法、构造器、代码块、内部类

基本语法:

class Outer{

class Inner{

}

}

class Other{

}

内部类的分类

定义在外部类局部位置上(比如方法内):

1)局部内部类(没有类名)

2)匿名内部类(没有类名,重点)

定义在外部类的成员位置上:

1)成员内部咧(没用static修饰)

2)静态内部类(使用static修饰)

局部内部类的使用

1)可以直接访问外部类的所有成员,包括私有的

2)不能添加访问修饰符,因为地位仅是一个局部变量,局部变量不能使用修饰符,但是可以用final修饰,局部变量也可以用final修饰

3)作用域:仅仅在定义它的方法或代码块中

4)局部内部类访问外部类成员(直接访问)

5)外部类访问局部内部类成员(创建对象,再访问,必须在作用域内)

class Outer{private int n1 = 100; private void m2() {}; //私有方法public void m1() {class Inner{public void f1() {System.out.println("n1 = " + n1); //可以访问外部类的私有成员m2();}}class Inner02 extends Inner{}}}

6)外部其他类不能访问局部内部类(因为地位是局部变量)

7)如果外部类和局部内部类的成语重名时,默认遵循就近原则,如果想访问外部类的成语,则可以使用(外部类名.this.成员)去访问

匿名内部类

1)本质是类

2)内部类

3)该类没有名字

4)同时还是一个对象

说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

1.匿名内部类的基本语法

new 类或接口(参数列表){

};

getclass();   得到编译类型

interface IA{public void cry();
}class A {public static void main(String[] args) {IA tiger = new IA() {public void cry() {System.out.println("....");}};//继承了IAtiger.cry();System.out.println("tiger的运行类型= " + tiger.getClass());/** 底层:* class XXX impements IA{ //创建A01&1实例,并把地址返回给tiger*        public void cry(){*         System.out.println("...");*       }* }*/}
}
class Father {public Father(String name) {//构造器}public void test() {};
}class Outer{Father father = new Father("jack") {public void test() {System.out.println("匿名内部类重写了test方法");}};
}class Father {public Father(String name) {//构造器}public void test() {};
}class Outer{Father father = new Father("jack") {public void test() {System.out.println("匿名内部类重写了test方法");}};
}

2.可以直接访问外部类的所有成员,包含私有的

3.不能添加访问修饰符,地位就是一个局部变量

4.作用域:仅仅在定义它的方法或代码块中

5.匿名内部类访问外部类成员->直接访问

//匿名内部类作实参

interface IL{void show();
}public class no1{public static void main(String[] args) {//当作实参直接传递,简介高效f1(new IL() {@Overridepublic void show() {// TODO Auto-generated method stubSystem.out.println("这是一副名画");}});}public static void f1(IL il) {il.show();}
}

成员内部类的使用

说明:成员内部类是定义在外部类的成员位置,并且没有static修饰。

1.可以直接访问外部类的所有成员,包含私有的

class Outer01{private int n1 = 10;public String name = "张三";class Inner01{public void say() {System.out.println("Outer01的n1 = " + n1 + "outer01的name = " + name);}}
}

2.可以添加任意访问修饰符(public、protected、默认、private),因为其就是一个成员

3.作用域和外部类的其他成员一样,为整个类体

4.成员内部类访问外部类——直接访问

5.外部类访问内部类——访问方式:创建对象,再访问

6.外部其他类访问成员内部类——创建对象,再访问

public class no1{public static void main(String[] args) {//外部其他类,使用成员内部类的三种方式//1Outer08 outer08 = new Outer08();Outer08.Inner08 inner08 = outer08.new Inner08();//2Inner08 inner012 = new Outer08().new Inner08();
//  outer08.t1();//3使用一个方法来获取,更加简洁。Inner08 inner01 = Outer08.getInner08Instance();}
}class Outer08{private int n1 = 10;public String name = "张三";private void hi() {System.out.println("hi()方法...");}//1.注意:成员内部类,是定义在外部类的成员位置上public class Inner08 {private double sal = 99.8;public void say() {//可以直接访问外部类的所有成员,包括私有的System.out.println("n1 = " + n1 + " name = " + name);hi();}}//得到inner08的方法public static Inner08 getInner08Instance() {return new Inner08();}public void t1() {//使用成员内部类//创建成员内部类的对象,然后使用相关的方法Inner08 inner08 = new Inner08();}
}

注意:如果成员内部类的成员和外部类的成员重名,会遵守就近原则。

静态内部类

说明:静态内部类是定义在外部类的成员位置,并有static修饰

1.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员

2.可以添加任意访问修饰符,因为它的地位就是一个成员。

3.作用域:整个类体

class outer{private int n1 = 10;private static String name = "张三";static class Inner02{public void say() {System.out.println(name);//不能直接访问外部类的非静态成员//System.out.println(n1);}}public void show() {//外部类使用内部类new Inner02().say();}
}

4.静态内部类访问外部类——直接访问所有静态成员

5.外部类访问静态内部类——访问方式:创建对象,再访问。


枚举

1)enum(enumeration)

2)枚举是一组常量的集合

3)枚举属于一种特殊的类,里面只包含一组有限的特定的对象

枚举的两种实现方式

1)自定义类实现枚举

2)使用enum关键字实现枚举

自定义类实现枚举

1.不需要提高set方法,因为枚举对象通常只为只读

2.对枚举对象/属性使用final static 共同修饰,实现底层优化。

3.枚举对象名通常使用全部大写,常量的命名规范

4.枚举对象根据需要,也可以有多个属性

public class no1{public static void main(String[] args) {System.out.println(Season.SPRING);}
}class Season{private String name;private String desc;//描述public static Season SPRING = new Season("春天", "温暖");public static Season SUMMER = new Season("夏天", "炎热");public static Season AUTUMN = new Season("秋天", "凉爽");public static Season WINTER = new Season("冬天", "寒冷");//1.将构造器私有化,目的:防止newprivate Season(String name, String desc) {this.name = name;this.desc = desc;}public String getName() {return name;}public String getDesc() {return desc;}@Overridepublic String toString() {return "Season [name=" + name + ", desc=" + desc + "]";}}

小结:

1)构造器私有化

2)本类内部创建一组对象

3)对外暴露对象(通过public final static修饰)

4)可以提供get方法,但不提供set方法

使用enum类实现枚举

1.使用关键字 enum 代替 class

2.SPRING(“春天”,“温暖”),。。。;

如果有多个常量对象,则用,号间隔。

3.如果使用enum,要求将定义常量对象写在最前面


public class no1{public static void main(String[] args) {System.out.println(Season.SPRING);}
}enum Season{SPRING("春天", "温暖"),SUMMER("夏天", "炎热");private String name;private String desc;//描述//1.将构造器私有化,目的:防止newprivate Season(String name, String desc) {this.name = name;this.desc = desc;}public String getName() {return name;}public String getDesc() {return desc;}@Overridepublic String toString() {return "Season [name=" + name + ", desc=" + desc + "]";}}

注意:

1)使用enum关键字开发一个枚举类时,默认会继承Enum类

2)简化成SPRING(" 春天 ","温暖");必须知道,调用的是哪个构造器

3)枚举对象必须放在枚举类的首行。

4)如果使用无参构造,则可以省略()

枚举类的成员方法

ordinal()输出的是该枚举对象的次序;

System.out.println(autumn.ordinal()); //从0开始编号

values()返回数组,含有所有枚举对象

Season2[] values = Season2.values();

for(Seasons2 season : values){ //增强for循环

System.out.println(season);

}

valueOf()    将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则异常报错。

Season2 autumn1 = Season1.valueOf("AUTUNM");

执行流程:

1.根据输入到Season2的枚举对象去查找

2.如果找到了就返回,如果没有找到就报错。

compare To() 比较两个枚举常量,比较的就是编号。

System.out.println(Season2.AUTUMN.compareTo(Season2.SUMMER);

enum实现接口:

1)使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而java是单继承机制。

2)枚举类和普通类一样,可以实现接口,如下:

enum 类名 implements 接口1,接口2{ }


注解

注解的理解:

1)注解(Annotation)也被称为元注释(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息

2)注解不影响程序逻辑性,但注解恶意被编译或运行

基本Annotation介绍

使用Annotation时要在其前面加 @ 符号,并把该Annotation当成一个修饰符使用。用于修饰它支持的程序元素

三个基本的Annotation:

1)@Override:限定某个方法,是重写父类方法,该注解只能用于方法

2)@Deprecated:表示某个程序元素(类、方法)已过时

3)@SuppressWarnings:抑制编译器警告

public class home {  public static void main(String[] args) {Son son = new Son();son.fly();}
}class Father{public void fly() {System.out.println("Father fly...");}
}class Son extends Father{//解读://1.@override注解放在fly方法上,表示子类的fly方法重写了父亲的fly//2.这里如果没有写@override还是重写了父亲的fly//3.如果你写了@override注解,编译器就会去检查该方法是否真的重写了父类的方法//  如果没有构成重写,则编译错误。@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println("Son fly...");}
}

注意:

1.@Override只能修饰方法,不能修饰其他类、包、属性等

2.查看@Override注解源码为@Target(ElementType,METHOD),说明只能修饰方法

3.@Target是修饰注解的注解,成为元注释

@Deprecated的说明

1.用于表示某个程序元素(类、方法)已过时

2.可以修饰方法、类、字段、包、参数等

3.@Target(value = {CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE})

4.@Deprected的作用可以做到新旧版本的兼容和过度

@SuppressWarning

all 抑制所有警告

boxing,抑制与封装/拆装作业相关的警告

cast,抑制与强制转型作业相关的警告

dep-ann,抑制与淘汰注释相关的警告

deprecation,抑制与淘汰相关的警告

fallthrough,抑制与未传回finally区块相关的警告

hiding,抑制与隐藏变数的区域变数相关的警告

incomplete-switch,抑制与switch陈述式(enum case)中遗漏项目相关的警告

javadoc,抑制与javadoc相关的警告

nls,抑制与非nls字串文字相关的警告

...

@SuppressWarning({"rawtypes","unchecked","unused"})

//unchecked 忽略没有检查的警告

//rawtypes 是忽略没有指定泛型的警告

//unused是忽略没有使用某个变量的警告错误

JDK的元注释Annotation

元注释的种类

1)Retention//指定注解的作业范围(SOURCE、CLASS、RUNTIME)

2)Target//指定注释可以在哪些地方使用

3)Document//指定该注解是否会在javadoc体现

4)Inherited//子类会继承父类注释

若@SuppressWarnings放置在main方法中,那么抑制的范围就是main

类图

常见异常

NumberFormatException数字格式不正确异常

当应用程序试图将字符串转换成一组数值类型,但该字符串不能转换为适当的格式时,就抛出该异常(使用异常可以确保输入是满足条件的数字)

编译异常

编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译。

常见的编译异常:

1) SQLException 操作数据库时,查询表可能发生异常

2)IQEEception 操作文件时,发生的异常

3)FileNotFoundException 当操作一个不存在的文件时发生异常

4)ClassnNotFoundExcepion 加载类,而该类不存在时,异常

5)EQFException 操作文件,到文件末尾,发生异常

6)IllegalArguementEception 参数异常


例题:

注意看D、E

例题:

        String fooString = "blue";boolean[] bar = new boolean[2];if(bar[0]) fooString = "g";System.out.println(fooString);//blue, 默认false

异常处理

如果进行异常处理,即使出现了异常,程序可以继续进行

基本概念:java语言中,将程序进行中发生的不正常情况成为“异常”(语法错误、逻辑错误不是异常)

两类异常事件

1)Error:java虚拟机无法解决的严重问题,如:JVM系统内部错误、资源耗尽等严重情况。比如栈溢出

2)Exception:隐编程错误或偶然的外在因素导致的一般性问题(编译时异常和运行时异常)

异常处理

1)try-catch-finally

程序员在代码中捕获发生的异常,自行处理

2)throws

将发生的异常抛出,交给调用者(方法)处理,最顶级的处理者就是JVM

try-catch

基本语法:

入门案例

    public static void main(String[] args) {try {String string = "hsp";int a = Integer.parseInt(string);System.out.println("数字 : "  + a );} catch (NumberFormatException e) {// TODO: handle exceptionSystem.out.println("异常信息=" + e.getMessage());}System.out.println("程序继续...");}

解读:

1)如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块

2)如果异常没有发生,则顺序执行try的代码块,不会进入到catch

注意:可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类在后,子类异常在前

    public static void main(String[] args) {try {Person person = new Person();int n1 = 10;int n2 = 0;int res = n1 / n2;} catch (NullPointerException e) {System.out.println("空指针异常" + e.getMessage());// TODO: handle exception} catch (ArithmeticException e) {System.out.println("算数异常" + e.getMessage());} catch (Exception e) {System.out.println(e.getMessage());}finally {}}

注意:可以进行try-finally配合使用,这种方法相当于没有补货异常,因此程序会直接崩

finally总是执行

例题1:

一个关于异常的小应用(判断输入)

    public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = 0;String inputString = "";while(true) {System.out.println("请输入一个数");inputString = scanner.next();try {num = Integer.parseInt(inputString);break;} catch (NumberFormatException e) {// TODO: handle exceptionSystem.out.println("你输入的不是一个整数");}}}

throws异常处理

1)如果一个方法(中的语句执行时)可能产生某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。

2)在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生异常的类型,也可以是他的父亲


Math类

public class Mathmethod {public static void main(String[] args) {int abs = Math.abs(-9);//求绝对值double pow = Math.pow(2, 4);//ceil 向上取整,返回大于等于该参数的最小整数(转成double)double ceil = Math.ceil((-3.0001));//floor向下取整,返回小于等于该参数的最小整数(转成double)double floor = Math.floor(3.1);//round四舍五入long round = Math.round(5.51);//sqrt开方double sqrt = Math.sqrt(9.0);//round 求随机数,随机返回0 <= x < 1之间的一个随机小数//随机返回一个数x 2 <= x <= 7//(int)(a)  <= x <= (int)(a + Math.random() * (b - a + 1 ));//max minint min = Math.min(2, 3);}
}

Arrays类

Arrays里包含了一系列静态方法,用于管理或操作数组(比如排序和搜索)

1)toString返回数组的字符串形式

import java.util.Arrays;public class Mathmethod {public static void main(String[] args) {Integer[] integers = {1, 20, 90};System.out.println(Arrays.toString(integers));//[1, 20, 90];}
}

2)sort方法

public class Mathmethod {public static void main(String[] args) {int[] a = {2, 1, 4 ,3};Arrays.sort(a);for(int i = 0; i < 4; i++) System.out.print(a[i] + " ");System.out.print(Arrays.toString(a));}
}

定制排序

参数1:数组

参数2:实现Comparator接口的匿名内部类,要求实现compare方法

public class Mathmethod {public static void main(String[] args) {Integer[] a = {2, 1, 4 ,3};Arrays.sort(a, new Comparator() {public int compare(Object o1, Object o2) {Integer i1 = (Integer)o1;Integer i2 = (Integer)o2;return i1 - i2;//从小到大}});}
}

冒泡+定制排序(注意接口的写法,以及bubble要静态)

public class Mathmethod {/* 要static */public static void bubble(int[] a, Comparator c) {for(int i = 0; i < a.length - 1; i++)for(int j = 0; j < a.length - i - 1; j ++){if(c.compare(a[j], a[j + 1]) > 0){int temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;}}}public static void main(String[] args) {int[] a = {2, 1, 4 ,3};bubble(a, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {// TODO Auto-generated method stubint i1 = (Integer)o1;int i2 = (Integer)o2;return i1 - i2;}});}
}

3)binarySearch通过二分搜索法进行查找,要求必须排好序,找不到返回-(low + 1)low为应该存在位置

public static void main(String[] args) {Integer arr[] = {1, 2, 3, 4};int idx = Arrays.binarySearch(arr, 1);}

4)copyOf数组元素的复制

public static void main(String[] args) {Integer arr[] = {1, 2, 3, 4};Integer a[] = Arrays.copyOf(arr, arr.length);}//如果要拷贝的长度>原长,则置空

如果拷贝长度<0,则抛出异常NegativeArraySizeException

该方法的底层使用的是System.arraycopy()

5)fill数组元素的填充

Integer arr[] = {1, 2, 3, 4};Arrays.fill(arr, 99);//[99,99,99,99]替换所有原来元素

6)equals判断两个数组是否一样

boolean equals = Arrays.equals(arr1, arr);

7)asList会将数组转成一个List集合

List asList = Arrays.asList(2, 3, 4);

System类

System类常见方法

1)exit退出当前程序

//exit退出程序System.out.println("0k1");System.exit(0);System.out.println("ok2");//输出ok1

2)arraycopy:复制数组元素,比较适合底层调用,一般使用Arrays.copyOf完成复制数组

        int a[] = {1, 2, 3};int b = new int[3];System.arraycopy(a, 0, b, 0, 3);//第一个参数:原数组//第二个参数:从原数组的第‘开始拷贝//第三个参数:目标数组//第四个参数:拷贝到目标数组的位置//第五个参数:拷贝多少个数据System.arraycopy(a, 0, b, 0, a.length);    

3)currentTimeMillens:返回当前时间距离1970-1-1的毫秒数

4)gc:运行垃圾回收机制System.gc();


BigInteger和BigDecimal类

应用场景:

1)BigInteger适合保存比较大的整形

2)BigDecimal适合保存精度更高的浮点型(小数)

1⃣️ add 加

2⃣️ substact 减

3⃣️ multiply

4⃣️ devide

        //当编程中需要处理很大的整数,long不够用//可以使用BigInteger的类来搞定BigInteger bigInteger = new BigInteger("233333333333333333333333");//字符串//1.在对BigInteger进行加减乘除的时候,需要使用对应的方法,不能直接加减。bigInteger.add(new BigInteger("122222"));
//当需要保存一个精度很高的数,double不够用//可以用BigDecimalBigDecimal bigDecimal = new BigDecimal("12.2222222222222");BigDecimal bigDecimal2 = new BigDecimal("11,1111111111111111");//可能会抛出异常ArithmeticEception//在调用divide方法时,指定精度即可//如果有无限循环小数,就会保留分子的精度System.out.println(bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING));

日期类

第一代日期类

1)Date:精确到毫秒,代表特定的时间

2)SimpleDateFormate:格式和解析日期的类,它允许格式化(日期->文本)(文本->日期)

        //引入util.date//默认输出格式是国外的方式Date date = new Date();System.out.println(date);//转换格式SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");String format = sdf.format(date);System.out.println(format);//Tue Feb 08 22:10:59 CST 2022//2022年02月08日 10:10:59 周二Date date2 = new Date(1111);//通过指定毫秒数得到时间//可以把一个格式化的字符串转成一个dateString s = "2022年02月08日 10:10:59 星期一";Date parse = sdf.parse(s); //bianyucuole?

第二代日期类 Calendar类(日历)

        //1.Calendar是一个抽象类,并且构造器private//2.可以通过getInstance(),来获取实例Calendar c = Calendar.getInstance();System.out.println(c);System.out.println("年: " + c.get(Calendar.YEAR));//月从0开始 +1System.out.println("月: " + (c.get(Calendar.MONTH) + 1));System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));//HOUR,MINUTE,SECOND...//若要24小时制则用HOUR_OF_DATE

Calendar存在问题:

1)可变性:像日期和时间这样的类应该是不可变的

2)偏移性:Date中的年份是从1900开始的,而月份都从0开始

3)格式化:格式化只对Date有效,而Calendar则不行

4)此外,他们也不是线程安全的,不能处理闰秒等(每隔两天多处1s)

第三代日期类(JDK8)

1)LocalDate(日期)、LocalTime(时间)、LocalDateTime(日期时间)

//第三代日期//1.使用now(),返回表示当前日期的对象LocalDateTime ldt = LocalDateTime.now();System.out.println(ldt);System.out.println("年=" + ldt.getYear());System.out.println("月=" + ldt.getMonth()); //englishSystem.out.println("日=" + ldt.getMonthValue());//numSystem.out.println("时=" + ldt.getHour());System.out.println("秒=" + ldt.getSecond());LocalDate now = LocalDate.now();//年月日LocalTime now2 = LocalTime.now();//时分秒

2)DateTimeFormatter格式日期类 类似于SimpleTimeFormatter格式日期类

//第三代日期//1.使用now(),返回表示当前日期的对象LocalDateTime ldt = LocalDateTime.now();DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH小时mm分钟ss秒");String formatString = dtf.format(ldt);System.out.println(formatString);

3)Instant时间戳

类似于Date

提供了一系列和Date转换的方式

//1.通过静态方法now()获取表示当前时间戳的对象Instant now = Instant.now();System.out.println(now);//2.通过from可以把Instant转成DateDate date = Date.from(now);//3.通过date的toInstant(),可以把date转成Instant对象Instant instant = date.toInstant();

4)第三代日期更多方法(用到时去查)

LocalDateTime类

MonthDay类:检查重复事件

是否闰年

增加日期某个部分

使用plus方法增加时间

使用minus查看一年前、一年后的时间


练习题

将字符串内指定部分进行翻转

public class Mathmethod {public static void main(String[] args) {String string = "abcde";try {string = reverse(string, 0, 4);} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage());return;}System.out.println(string);}//将字符串中指定部分进行反转+异常处理public static String reverse(String s, int st, int ed){//对参数进行验证if(!(s != null && st >= 0 && ed > st && ed < s.length())) {throw new RuntimeException("参数不正确");}int p1 = st, p2 = ed;char[] a = s.toCharArray();char tmp;while(p1 != p2){tmp = a[p1];a[p1++] = a[p2];a[p2--] = tmp;}return new String(a);}
}

注册处理题

要求:

(1)用户名长度为2、3、4

(2)密码长度为6,要求全是数字 isDigital

(3)邮箱中包含@和. 并且@在.前

public static void main(String[] args) {String name = "jack";String pwdString = "123456";String emailString = "jack@souhu.com";try {userRegister(name, pwdString, emailString);System.out.println("注册成功");} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage());}}public static void userRegister(String name, String pwd, String email){int userLength = name.length();if(!(userLength >= 2 && userLength <= 4)) {throw new RuntimeException("用户名长度为2或3或4");}if(!(pwd.length() == 6 && isDigtal(pwd))){throw new RuntimeException("密码长度为6,要求全为数字");}int i = email.indexOf('@');int j = email.indexOf('.');if((i > 0 && j > i)){throw new RuntimeException("邮箱不正确");}}public static boolean isDigtal(String str){char[] chars = str.toCharArray();for(int i = 0; i < chars.length; i++){if(chars[i] < '0' || chars[i] > '9') return false;}return true;}

集合

1)可以动态保存任意多个元素

2)提供了一系列方便的操作对象的方法:add、remove、set、get

3)使用集合添加,删除新元素的代码

Collection接口有两个重要的子接口 List、Set(单列)

Map双列集合

Collection接口和常用方法

1)collection实现子类可以存放多个元素,每个元素可以是Object

2)有些Colletion的实现类,有些有序(List)、有些无序(Set)

3)Colletcion接口没有直接的实现子类,是通过他的子接口Set和List来实现的

List list = new ArrayList();//add:添加单个元素list.add("jack");list.add(10); //list.add(new Integer(10))list.add(true);//remove:删除指定元素list.remove(0); //删除第一个元素list.remove("jack"); //指定删除某个元素//contains:查找元素是否存在list.contains("jack");//size:返回元素个数list.size();//isEmpty:判断是否为空list.isEmpty();//list.clear();//addAll:添加多个元素ArrayList list2 = new ArrayList();list2.add("红楼梦");list2.add("三国演义");list.addAll(list2);//removeAll:删除多个元素list.removeAll(list2);

Collection接口遍历元素方式1-使用Iterator(迭代器)

Iterator迭代器

实现了Colletcion接口的结合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。

注意:在调用iterator.next()方法之前,必须要调用iterator.hasNext()进行检测。若不调用,且下一条无效,直接调用it.next()会抛出NoSuchElementException异常

public class CollectionMethod {public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book("三国演义","罗贯中",10.1));Iterator iterator = col.iterator();while(iterator.hasNext()){//返回下一个元素,(编译)类型是ObjectObject obj = iterator.next();System.out.println(obj);//动态绑定}}
}
class Book
{String name;String author;double price;public Book(String name, String author, double price) {super();this.name = name;this.author = author;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Book [name=" + name + ", author=" + author + ", price=" + price + "]";}}

Collection接口遍历对象方式2-for循环增强

基本语法:

for(元素类型 元素名:集合名/数组名)

for(Object obj : col) {

}

注意:

底层仍然是迭代器

public class CollectionMethod {public static void main(String[] args) {Collection col = new ArrayList();col.add(new Book("三国演义","罗贯中",10.1));for(Object book : col){System.out.println(book);}}
}
class Book
{String name;String author;double price;public Book(String name, String author, double price) {super();this.name = name;this.author = author;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Book [name=" + name + ", author=" + author + ", price=" + price + "]";}}

List接口和常用方法

List接口基本介绍:

1)List集合类中的元素有序(即添加顺序和取出顺序一致)、且可重复

2)List集合中的每个元素都有其对应的顺序索引,即支持索引。

3)List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

4)JDK API中List接口的实现常用类有:ArrayList、LinkedList和Vector

List list = new ArrayList();list.add("张三丰");list.add("b");//在index位置插入ele元素list.add(1,"ha");//从idx位置开始将else中所有元素都加进来List list2 = new ArrayList<>();list2.add("1");list.addAll(1,list2);//获取指定idx位置的元素//Object get(int idx)//返回obj在集合中首次出现的位置list.indexOf("b");//返回obj在集合中国末次出现的位置list.lastIndexOf("b");//移除指定位置idx的元素list.remove(0);//设置指定idx位置的元素(替换)list.set(0, "1");//返回从idx1-idx2的子集合List returnList = list.subList(0, 2);//0-1System.out.println("list = " + list);
for (int i = 0; i < List.size(); i++) {System.out.println(List.get(i));}

Arraylist的注意事项

1)permits all element,including null

2)由数组实现存储

3)基本等于Vector,除了ArrayList是线程不安全的(执行效率高)

多线程情况下不建议使用ArrayList

ArrayList底层结构和源码分析

1)ArrayList中维护了一个Object类型的数组elementData

transient Object[] elementData;//transient 表示该属性不会被序列化

2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加扩容为10,如需再次扩容,则扩容为elementData的1.5倍

3)如果使用的是指定大小的构造器,则初始elementData容量大小为指定大小,如果需要扩容,则直接扩容为elementData容量的1.5倍

510.ArrayList底层源码


Vector注意事项

1)Vector底层也是一个对象数组,protected Object[] elementData

2)Vector是线程同步的,即线程安全,方法带有synchronized

3)开发中考虑线程同步,用vector

4)扩容机制:

无参,默认10,满后2倍扩

指定大小,每次2倍扩


LinkList底层结构

1)LinkedList底层实现了双向链表和双端队列的特点

2)可以添加任意元素(元素可以重复)包括null

3)线程不安全,没有实现同步

属性:first、last

每个节点维护了prev、next、item属性

CRUD增删改查


Set

1)无序

2) 不允许元素重复,所以最多包含一个null

3)常用方法和Colletion接口一样

Set 不能使用索引的方式来获取

Set接口的实现的对象(Set接口对象),不能存放重复元素,且无序

取出的顺序是固定的(不是添加的顺序

Set set = new HashSet<>();set.add("a");set.add("b");set.remove("a");Iterator iterator = set.iterator();

HashSet

1)HashSet实现了Set接口

2)HashSet实际上是HashMap(底层是HashMap)

3)可以存放null值,但只能1个

4)HashSet不保证元素是有序的,取决于hash后,再确定索引的结果

5)不能有重复元素/对象

6)在执行add后会返回一个bool值

public class CollectionMethod {public static void main(String[] args) {Set set = new HashSet<>();set.add("a");set.add("a");//falseset.add(new dog("a")); //trueset.add(new dog("a")); // true}
}
class dog
{String name;public dog(String name) {super();this.name = name;}
}

HashSet底层是链表+数组+红黑树

1)添加一个元素时,先得到hash值

2)找到存储数据表table,看这个索引位置是否已经有存放的元素

3)如果没有,直接加入

4)如果用,调用equals比较,如果相同就放弃添加,如果不相同,则添加到最后

5)在Java8中,如果一条链表的元素个数超过TREEIFY——THRESHOLD(默认8),并且table大小 A  >= Min_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)

HashSet扩容和转成红黑树机制

1)HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFacotor)是0.75 = 12

2)如果table数组使用到了临界值12就会扩容到16*2 = 32,新的临界值就是32 * 0.75 = 24,以此类推。

3)在Java8中,如果一条链表的元素个数超过TREEIFY——THRESHOLD(默认8),并且table大小 A  >= Min_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树),否则仍采用数组扩容机制

重写Hashcode和equals

    @Overridepublic int hashCode() {return Objects.hash(name);}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;dog other = (dog) obj;return Objects.equals(name, other.name);}

LinkedHashSet

1)LinkedHashSet是HashSet的子类

2)LinkedHashSet底层是一个LInkedHashMap(HashMap的子类),底层维护了一个数组+双向链表

3)LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的

4)LinkedHashSet不允许添加重复元素

说明:

1)在LinkedHashSet中维护了一个hash表和双向链表(有head 和 tail)

2)在每个节点有pre和next属性,这样可以形成双向链表

3)在添加一个元素时,先求hash值,在求索引,确定该元素在hashtable的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加)

4)能够确保遍历LinkedHashSet顺序和插入顺序一致

tail.next = newElement;

5)第一次添加时,直接将数组table扩容到16,数组时HashMapNode[]存放的结点类型时LinkedHashMapEntry(数组多态,二者内部有继承关系)

newElement.pre = tail

tail = newElement

hashcode和equals都相同,才不能加进表内


Map

Map接口特点:

1)Map和Collection并列存在,用于保存具有映射关系的key-value

2)Map中的key和value可以是引用类型的数据,会封装到HashMapNode对象中

3)Map中的key不允许重复

4)Map中的value可以重复

5)Map中的key可以为null,value也可以为null,注意:只能有一个key为null, 可以有多个value为null

6)常用String类型为key

7)key和value之间存在单向一对一关系,即通过指定的key找到相对应的value

8)Map中k-v是放在一个Node结点的

解读:

1.k - v最后是 HashMapNode node = newNode(hash, key, value, null)

2.k - v 为了方便程序员的遍历, 还会创建EntrySet集合,该集合存放的元素的类型是Entry,而一个Entry对象就要k,v,EntrySet<Entry<K,V>>

3.在entrySet中定义的类型是Map.Entry, 但实际上存放的还是HashMapNode,这是因为HashMapNode implments Map.Entry

4.当把HashMapNode对象存放到entrySet (一个容器,指向各Node元素)就方便我们遍历,因为Map.Entry提供了重要方法

K getKey(), V getValue();

Map接口和常用方法

        Map map = new HashMap<>();//put添加map.put("邓超", new Book("", 100));map.put("邓超", "孙俪") // 替换了bookmap.put("王宝强", "马蓉");//removemap.remove(null);//getObject val = map.get("邓超");//sizeSystem.out.println(map.size());//isEmptySystem.out.println(map.isEmpty());//map.clear();//containsKey 查找键是否存在System.out.println(map.containsKey("hsp"));

Map遍历方法

        Map map = new HashMap<>();//put添加map.put("邓超", new Book("", 100));map.put("邓超", "孙俪");// 替换了bookmap.put("王宝强", "马蓉");//1:先取出所有key,通过key取出对应valueSet keySet = map.keySet();//(1)for(Object key : keySet) {System.out.println(key + "-" + map.get(key));}System.out.println("------------");//(2) Iterator iterator = keySet.iterator();while(iterator.hasNext()) {Object keyObject = iterator.next();System.out.println(keyObject + "-" + map.get(keyObject));}System.out.println("------------");//2.把所有的value取出Collection values = map.values();for(Object value : values) {System.out.println(value);}System.out.println("------------");//3.通过Entry,来获取k-v//(1)Set entrySet = map.entrySet();for(Object entry : entrySet){//将entry转成Map.EntryMap.Entry m = (Map.Entry) entry;System.out.println(m.getKey() + "-" + m.getValue());}//(2)Iterator iterator3 = entrySet.iterator();while(iterator3.hasNext()){Object entry = iterator3.next();//向下转型 Map.EntryMap.Entry m = (Map.Entry)entry;System.out.println(m.getKey() + "-" + m.getValue());}

HashMap底层机制及源码剖析

扩容机制

1)HashMap底层维护了Node类型的数组table,默认为null

2)当创建对象时,将加载因子(loadfactor)初始化为0.75

3)当添加key-val时,通过key的哈希值得到在table的索引,然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换val;如果不相等需要判断是树结构还是链表结构,作出相应处理,如果添加时发现容量不够,则需要扩容

4)第一次添加,则需要扩容table容量为16,临界值(threshold)为12

5)以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,依此类推

6)在Java8中,如果一条链表的元素个数超过TREEIFY_ThRESHOLD(默认是8),并且table的大小>=MIN_TERRIFY_CAPACITY(默认64),就会进行树化(红黑树)


Map接口实现类——HashTable

基本介绍:

1)存放键值对

2)hashtable的键和值都不能是null,否则会抛出NulPointerException

3)hashTable使用方法基本和HashMap一样

4)hashTable是线程安全的(HashMap是线程不安全的)

5)简单说明Hashtable的底层

1.底层有素组HashtableEntry[] 初始化大小为11

2.threshold 8 = 11 * 0.75

3.扩容:执行 方法addEntry(hash,key,value,index)添加 K-V封装到Entry

当if(count > threshold)满足时就扩容

按照 int newCapcity = (oldCapacity << 1 ) + 1;的大小扩容

Map接口实现类-Properties

1.Properties类继承自Hashtable类并实现了Map接口,也是使用一种键值对的形式来保存数据

        Properties properties = new Properties();properties.put("john", 100);System.out.println(properties.get("john"));//修改properties.put("john", 200);//removeproperties.remove("john");

总结:开发中如何选择集合实现类

1)单列? 双列?

2)一组对象:Collection接口

允许重复:List

增删多:LinkedList(双向链表)

改查多:ArrayList(底层维护了Object类型可变数组)

不允许重复:Set

无序:HashSet(底层是HashMap,维护了一个哈希表(数组+链表+红黑树))

排序:TreeSet

插入与取出顺序一致:LinkedHashSet(数组+双向链表)

3)一组键值对:

键无序:HashMap(数组+链表+红黑树)

键排序:TreeMap

键插入与取出顺序一致:LinkedHashMap

读取文件:Properties


TreeMap

当使用无参构造器,创建TreeSet时,仍是无序的

使用TreeSet提供的构造器,可以传入一个比较器(匿名内部类)//实现Comparator接口

        public static void main(String[] args) {TreeSet treeSet = new TreeSet(new Comparator() {@Overridepublic int compare(Object o1, Object o2) {// TODO Auto-generated method stubreturn ((String) o1).compareTo((String) o2);}});treeSet.add("jack");treeSet.add("tom");treeSet.add("sp");System.out.println(treeSet);}

代码备注:若按长度排序,再加一个长度为2的字符串,则加不进去,cmp会退出


Collection工具类

介绍:

1)Collection是一个操作Set、List、Map等集合的工具

2)Collection中提供了一系列静态的方法对集合元素进行排序、查询、修改等操作

排序操作(均为static方法)

ArrayList list = new ArrayList();list.add("tom");list.add("simth");list.add("king");Collections.reverse(list); //反转List集合中的元素System.out.println("list = " + list); Collections.shuffle(list); //对List集合元素进行随机排序System.out.println("list = " + list);Collections.sort(list); //根据元素自然顺序对指定List集合进行升序排序//若希望按字符串长度大小排序Collections.sort(list, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {// TODO Auto-generated method stubreturn ((String)o1).length() - ((String)o2).length();}});//swap(list, int i, int j)Collections.swap(list, 0, 1);

有个swap函数

        ArrayList list = new ArrayList();list.add("tom");list.add("simth");list.add("king");//maxCollections.max(list, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {// TODO Auto-generated method stubreturn ((String)o1).compareTo((String) o2);}});//min//frequencySystem.out.println(Collections.frequency(list, "tom"));//将src中的内容复制到dest中//为了完整的拷贝,需要先给dest赋值,大小和list.size()一样;ArrayList list2 = new ArrayList();for(int i = 0; i < list.size(); i++) {list2.add("");}Collections.copy(list2, list);//替换Collections.replaceAll(list, "tom", "ban");

类图


题目1:

(1)封装新闻类,包含标题和内容属性,提供get、set方法

(2)倒叙遍历

(3)遍历集合时,对新闻标题进行处理,超过15字的只保留前15个,然后后面+...

public class HashTableExercise {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add(new News("。。。。。。。。。。............。。。。。。。。...。。。。。。"));int size = arrayList.size();for(int i = size - 1; i >= 0; i--){News news= (News)arrayList.get(i);System.out.println(processtext(news.getText()));}}public static String processtext(String title){if(title == null) return " ";if(title.length() > 15) {return title.substring(0, 15) + " ";//[0,15)}else return title;}
}class News
{String text;public String getText() {return text;}public void setText(String text) {this.text = text;}public News(String text) {super();this.text = text;}}

//传入对象需实现Comparable接口,否则会报错(不传入比较器情况下)


泛型

1)泛型又称参数化类型,解决数据类型安全性问题

2)在类声明或实例化时只要指定好需要的具体的类型即可

3)java泛型可以保证如果程序在编译时没有发出警告,运行时既不会产生ClassCastException异常

4)泛型的作用:可以在类声明时通过一个标识表示类中的某个属性,或者是某个方法的返回值的类型,或者是参数类型

public class Generic {Person<String> person = new Person<String>("hso");
}class Person<E>{E s;public Person(E s) {this.s  = s;}public E f() {reurn s;}
}

泛型的语法

interface 接口<T> {}

class <K, V> { }

使用样例——注意语法

public class hashmap1 {public static void main(String[] args) {HashSet<Student> students = new HashSet<Student>();students.add(new Student("jack", 18));//for迭代for(Student student : students) {System.out.println(student);}HashMap<String, Student> hMap = new HashMap<String, Student>();hMap.put("milan", new Student("milan", 38));//迭代器使用Set<Map.Entry<String, Student>> entries = hMap.entrySet();Iterator<Map.Entry<String, Student>> iterator = entries.iterator();while (iterator.hasNext()) {Map.Entry<java.lang.String, work1.Student> next =  iterator.next();System.out.println(next.getKey() + ' ' + next.getValue());}}}class Student
{String name;int id;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public Student(String name, int id) {super();this.name = name;this.id = id;}@Overridepublic String toString() {return "Student [name=" + name + ", id=" + id + "]";}}

注意:

1)T、E只能是引用类型,不能是基本数据类型如int

2)在给泛型指定具体类型后,可以传入该类型或者其子类类型

3)在实际开发中,我们往往简写(编译器会自动判断类型)

ArrayList<Integer> list3 = new ArrayList<>();

4)如果不写泛型,则默认为object类型


自定义泛型

class 类名 < T, R...>{ }

注意:

1)普通成员可以使用泛型(属性、方法)

2)使用泛型的数组,不能初始化

3)静态方法中不能使用类的泛型(因为静态是和类相关的,在类加载时,对象还没创建,所以不能使用)

4)泛型类的类型,是在创建对象时确定的

5)如果在创建对象时,没有指定类型,默认是Object

interface 接口名 <T, R,...> {

}

注意:

1)接口中,静态成员也不能使用泛型

2)泛型接口的类型,在继承接口或实现接口时确定

3)没有指定类型,默认为Object

自定义泛型方法

修饰符<T, R....> 返回类型 方法名(参数列表) {
}

注意:

1)泛型方法,可以定义在普通类中,也可以定义在泛型类中

2)当泛型方法被调用时,类型会确定

3)public void eat(E e){}

这不是泛型方法,而是使用了泛型

泛型的继承和通配符

1)泛型不具备继承型

List<Object> list = new ArrayList<String>(); //不可以

2)<>>:支持任意泛型类型

3)<? extends A> :支持A类以及A类的子类,规定了泛型的上限

4)<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限


JUnit

为什么需要?

一个类有很多功能代码需要测试,为了测试,就需要写到main,效率低

基本介绍:

1)JUnit是一个Java语言的单元测试框架

2)在测试代码前输入@Test


java绘图坐标体系

坐标原点位于左上角,以像素为单位。

像素是一个密度单位

例:计算机显示器的分辨率为800*600,表示计算机屏幕上的每一行由800个点组成,共有600行

java绘图技术

绘图原理:

1)paint(Graphics g)绘制组件外观

2)repaint()刷新组件外观

当组件第一次在屏幕显示的时候,程序会自动调用paint()方法来绘制组件

在以下情况下paint()会被调用

1)窗口最小化,再最大化

2)窗口的大小发生变化

3)repaint函数被调用

package work1;import java.awt.Graphics;import javax.swing.JFrame;
import javax.swing.JPanel;public class DrawCircle extends JFrame{ //JFrame是面板(框框)//定义一个面板private Mypanel mp = null;public static void main(String[] args) {new DrawCircle();}public DrawCircle(){//初始化面板mp = new Mypanel();//把面板放到窗口(画框)this.add(mp);//设置窗口大小this.setSize(400, 300);this.setDefaultCloseOperation(JFrame, EXIT_ON_CLOSE);//当点击窗口的小叉程序就退出this.setVisible(true);//可以显示}
}//1.先定义一个面板(Panel),继承JPanel类,画图形,在面板上画
class Mypanel extends JPanel {@Overridepublic void paint(Graphics g) { //绘图方法//Graphics g g理解为一支画笔// TODO Auto-generated method stubsuper.paint(g);//调用父类的方法,完成初始化g.drawOval(10,10, 100, 100); //画椭圆}
}

java绘图技术

画一个蓝色的矩形(根据上面的代码)

        g.setColor(Color.blue);g.fillRect(10, 10, 100, 100);

画图片

1. Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bg.png"));

/bg 表示在该项目的根目录去获取bg.png图片资源

g.drawImage(image, 10, 10, 175, 221, this);

//根据图片的实际大小绘图,否则会变形

//给画笔设置颜色和字体 g.setColor(Color.red);
g.setFont(new Font("隶书", Font.BOLD, 50));
//这里设置的 100, 100, 是 "北京你好"左下角
g.drawString("北京你好", 100, 100);//设置画笔的字体 setFont(Font font)
//设置画笔的颜色 setColor(Color c)

java事件处理机制

implements KeyListener(监听键盘键)

package com.hf;import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;import javax.swing.JFrame;
import javax.swing.JPanel;public class ballmove extends JFrame{MyPanel mp = null;public static void main(String[] args) {ballmove b = new ballmove();}public ballmove() {// TODO Auto-generated constructor stubmp = new MyPanel();this.add(mp);//JFrame监听键盘事件this.addKeyListener(mp);//重要一步//this.setSize(400, 300);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setVisible(true);}
}//画一个小球
//
class MyPanel extends JPanel implements KeyListener
{int x = 10;int y = 10;@Overridepublic void paint(Graphics g) {// TODO Auto-generated method stubsuper.paint(g);g.fillOval(x, y, 20, 20);}//有字符输出时,该方法就会触发@Overridepublic void keyTyped(KeyEvent e) {// TODO Auto-generated method stub}//当某个键按下,触发@Overridepublic void keyPressed(KeyEvent e) {// TODO Auto-generated method stub//根据用户按下的键,进行移动小球//在java中会给每个键分配一个值if(e.getKeyCode() == KeyEvent.VK_DOWN) { //KeyEvent.VK_DOWN就是向下的箭头对应的codey++;}else if(e.getKeyCode() == KeyEvent.VK_UP) {y--;}else if(e.getKeyCode() == KeyEvent.VK_LEFT) {x--;}else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {x++;}//重绘this.repaint();}//当某个键释放,触发@Overridepublic void keyReleased(KeyEvent e) {// TODO Auto-generated method stub}}

java事件处理采用“委派事件模型”,(委派对象和处理对象不同)

事件源是一个产生事件的对象,比如按钮、窗口

事件:事件就是承载事件源状态改变时的对象,比如当键盘事件、鼠标时间、窗口事件等等,会生成一个事件对象,该对象保存着当前很多信息,比如KeyEvent对象有含有被按下键的Code值

事件处理机制深度理解:

(1)当事件源产生一个事件,可以传给事件监听者处理

(2)事件监听者实际上就是一个类,该类实现了某个事件监听接口比如前面我们案例中的MyPanle就是一个类,它实现了KeyListener接口,可以作为事件监听者,对接收到的事件进行处理

(3)事件监听接口有很多种,不同的事件监听器接口可以监听不同的事件、一个类可以实现多个监听接口

(4)这些接口在java.awt.event包和javax.swing.event包中定义。

______坦克大战———


线程

线程相关概念

程序:为完成特定任务,用某种语言编写的一组指令的集合(代码)

进程:

1.进程是指运行中的程序,比如使用qq,就启动了一个进程,操作系统就会为该进程分配内存空间

2.进程时程序的一次执行过程,或是正在运行的一个程序,是动态过程,有它自身的产生、存在和消亡的过程

线程:

1.线程由进程创建,是进程的一个实体

2.一个进程可以拥有多个线程,比如:一个qq进程,可以同时打开多个聊天窗口

3.并发:同一个时刻,多个任务交替执行,造成一种“貌似同时”的错觉,简单的说,单核cpu实现的多任务就是并发

4.并行:同一个时刻,多个任务同时进行。多核cpu可以实现并行

获取cpu数量

    public static void main(String[] args) {Runtime runtime = Runtime.getRuntime();//获取当前电脑的cpu数量int cpuNums = runtime.availableProcessors();System.out.println(cpuNums);}

线程基本使用

在java中线程有两种使用方法

1)继承Thread类,重写run方法

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

例:

import javax.xml.catalog.Catalog;
import javax.xml.catalog.CatalogException;public class homework01 {public static void main(String[] args) {//创建cat对象,可以当作线程使用Cat cat = new Cat();cat.start();//启动线程}
}class Cat extends Thread{//当一个类继承了Thread类,该类就可以当作线程使用//我们会重写run方法,写上自己的业务代码//run Thread类 实现了Runnable接口的run方法@Overridepublic void run() {int times = 0;// TODO Auto-generated method stubwhile(true) {//每个一秒输出“  “times ++;System.out.println("喵喵,我是小猫咪");//让该线程休眠一秒try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO: handle exceptione.printStackTrace();}if(times == 10) break;}}
}

java学习笔记第三部分相关推荐

  1. Java学习笔记项目三:开发团队调度软件(尚硅谷)

    JAVA学习笔记开发团队调度软件 ①创建基础组件 Equipment 接口 package august.domain;/*** 设备领取** @author : Crazy_August* @Dat ...

  2. Java学习笔记(三):流程控制

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://mp.csdn.net/mdeditor/100662793 目录 ...

  3. Java学习笔记(三十五)

    在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度.现在将跟着视频做的笔记进行整理.本篇博客是整理Java知识点的第三十五 ...

  4. C语言、Java学习笔记(三)---几种简单的排序算法

    假期已经过了一半,整个人都变得颓废了许多.今天没有出去玩,就学了几个简单的排序算法,以求安慰自己,好歹也是在假期里学习过了.(瘫- C 这里一次性给出三种排序方法的代码,分别是冒泡排序,选择排序和归并 ...

  5. JAVA学习笔记(三) 实现类

    这一节,我们要学会一些基本的实现类的操作,理解构造函数的作用和用法. 目录 一.实例变量和封装 1.变量 2.封装 二.指定类的公共接口 指定方法 指定构造函数&为公共接口注释 案例测试 三. ...

  6. java学习笔记第三章

    三.数组 & 常用类 数组Array基本概念: 一维数组.二维数组.多维数组 数组是相同数据类型(可以为任意类型数据)的有序集合,通过索引来引用 数组也是对象:数组元素相当于对象的成员变量 数 ...

  7. Java学习笔记(三)--Java主类结构

    目录 Java语言基础(一) 一.Java主类结构 1.1 Java主类程序例子 1.2 程序解析 1.3 Java语言规范 1.4 命名习惯 二.代码注释与编码规范 2.1 代码注释 2.2 编码规 ...

  8. JAVA学习笔记(三)

    JavaBean的基本需求 属性:private Type *** 提供属性的存取方法 取方法命名:get*** 存方法命名:set*** 提供缺省(无参)的构造器 继承 Java不能多重继承,可以多 ...

  9. B站韩顺平java学习笔记(三)--运算符章节

    目录 一.算术运算符 1.  表格 2.  练习题: 二. 关系运算符 1.  表格 三.逻辑运算符 1.  表格 2.  练习题 四.赋值运算符 1.  介绍 2.细节特点 五.三元运算符 1.  ...

最新文章

  1. 和12岁小同志搞创客开发:检测按键状态的两件法宝
  2. 创建、编辑、删除目录
  3. python matplotlib.pyplot.xticks() yticks() (设置x或y轴对应显示的标签)
  4. 下取整函数的含义_Excel将3.14159取值为3.15或3.1415? 两个函数为你效劳,拿走不谢...
  5. JAVA实现SFTP实例(JSCH)
  6. java实现插入排序 1
  7. Java面向对象编程篇6——注解与反射
  8. Openfire性能优化与压力测试小结
  9. jsf 导航_JSF导航规则示例教程
  10. 跨域认证--使用Passport
  11. Photoshop 入门教程「9」如何增加画布的空间?
  12. K8S集群安装Pod网络附加组件
  13. log4j WARN 和 SLF4J WARN 解决办法
  14. 用 Pinbox 轻松收藏代码,这就是我要的收藏工具
  15. 巧妙地数组之类的数据平移
  16. 动漫头像修复高清,提高分辨率、提高清晰度的模型处理
  17. 华为服务器虚拟化收费标准,HCS-Solution-IT-华为服务器虚拟化解决方案-03配置报价指导_华为虚拟化软件价格...
  18. s3c6410 Booting模式
  19. 百度百科创建词条怎么引用参考文献,哪些新闻可以作为百度百科参考资料
  20. ajax 设置同步请求

热门文章

  1. C++复习炒剩饭(1)心一意
  2. # 初步认识 VR / AR
  3. 院校-美国:美国国立卫生研究院(NIH)
  4. 蓝牙耳机什么牌子好_盘点千元内最好的蓝牙耳机
  5. iOS - 接入 Live2D
  6. Java-装箱和拆箱(谁动了我的变量?)
  7. 在计算机上配置dns,常见设备和系统上配置DNS的方法DNS服务器 -电脑资料
  8. ApowerREC 1.2.4破解版 亲测能用
  9. phython在file同时写入两个_Flink集成数据湖之实时数据写入iceberg
  10. office使用技巧大全