java学习笔记第三部分
接口
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来。
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学习笔记第三部分相关推荐
- Java学习笔记项目三:开发团队调度软件(尚硅谷)
JAVA学习笔记开发团队调度软件 ①创建基础组件 Equipment 接口 package august.domain;/*** 设备领取** @author : Crazy_August* @Dat ...
- Java学习笔记(三):流程控制
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://mp.csdn.net/mdeditor/100662793 目录 ...
- Java学习笔记(三十五)
在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度.现在将跟着视频做的笔记进行整理.本篇博客是整理Java知识点的第三十五 ...
- C语言、Java学习笔记(三)---几种简单的排序算法
假期已经过了一半,整个人都变得颓废了许多.今天没有出去玩,就学了几个简单的排序算法,以求安慰自己,好歹也是在假期里学习过了.(瘫- C 这里一次性给出三种排序方法的代码,分别是冒泡排序,选择排序和归并 ...
- JAVA学习笔记(三) 实现类
这一节,我们要学会一些基本的实现类的操作,理解构造函数的作用和用法. 目录 一.实例变量和封装 1.变量 2.封装 二.指定类的公共接口 指定方法 指定构造函数&为公共接口注释 案例测试 三. ...
- java学习笔记第三章
三.数组 & 常用类 数组Array基本概念: 一维数组.二维数组.多维数组 数组是相同数据类型(可以为任意类型数据)的有序集合,通过索引来引用 数组也是对象:数组元素相当于对象的成员变量 数 ...
- Java学习笔记(三)--Java主类结构
目录 Java语言基础(一) 一.Java主类结构 1.1 Java主类程序例子 1.2 程序解析 1.3 Java语言规范 1.4 命名习惯 二.代码注释与编码规范 2.1 代码注释 2.2 编码规 ...
- JAVA学习笔记(三)
JavaBean的基本需求 属性:private Type *** 提供属性的存取方法 取方法命名:get*** 存方法命名:set*** 提供缺省(无参)的构造器 继承 Java不能多重继承,可以多 ...
- B站韩顺平java学习笔记(三)--运算符章节
目录 一.算术运算符 1. 表格 2. 练习题: 二. 关系运算符 1. 表格 三.逻辑运算符 1. 表格 2. 练习题 四.赋值运算符 1. 介绍 2.细节特点 五.三元运算符 1. ...
最新文章
- 和12岁小同志搞创客开发:检测按键状态的两件法宝
- 创建、编辑、删除目录
- python matplotlib.pyplot.xticks() yticks() (设置x或y轴对应显示的标签)
- 下取整函数的含义_Excel将3.14159取值为3.15或3.1415? 两个函数为你效劳,拿走不谢...
- JAVA实现SFTP实例(JSCH)
- java实现插入排序 1
- Java面向对象编程篇6——注解与反射
- Openfire性能优化与压力测试小结
- jsf 导航_JSF导航规则示例教程
- 跨域认证--使用Passport
- Photoshop 入门教程「9」如何增加画布的空间?
- K8S集群安装Pod网络附加组件
- log4j WARN 和 SLF4J WARN 解决办法
- 用 Pinbox 轻松收藏代码,这就是我要的收藏工具
- 巧妙地数组之类的数据平移
- 动漫头像修复高清,提高分辨率、提高清晰度的模型处理
- 华为服务器虚拟化收费标准,HCS-Solution-IT-华为服务器虚拟化解决方案-03配置报价指导_华为虚拟化软件价格...
- s3c6410 Booting模式
- 百度百科创建词条怎么引用参考文献,哪些新闻可以作为百度百科参考资料
- ajax 设置同步请求