文章目录
注释
- 单行注释
- 多行注释
- 文档注释
public class Demo {
public static void main(String[] args) {
// 单行注释
/*
* 多行注释
* */
/**
* 文档注释
*/
System.out.println("开始注释");
}
}
字面量
告诉程序员:数据在程序中的书写形式
整数型字面量:1 、2、 3 、100、 -100、 -20 …
浮点型字面量:1.3 、1.2、 3.14…
布尔型字面量:true、false没有其它值了,表示真和假,true表示真,false表示假
字符型字面量:‘a’、‘b’、‘中’
字符串型字面量:“abc”、“a”、“b”、“中国”
所有的字符型只能使用单引号括起来。
所有的字符串型只能使用双引号括起来
关键字
Java语言中已经赋予了特定含义的
标识符
用来标识类名、对象名、变量名、方法名、类型名、数组名、文件名的有效字符序列。
命名规则
由字母、数字、下划线“_”、美元符号“$”或者“¥”组成
首字符不能是数字
不能把java关键字和保留字作为标识符。
标识符对大小写敏感
// 也是正确的
int 数字 = 100;
System.out.println(数字);
建议规范
变量
含义
变量其实就是内存当中存储数据的最基本的单元。
存数据用的,而且这个数据是可变的,所以叫做变量
作用
如果只有字面量,没有变量机制的话,下面代码虽然都是10,但是这3个10占用三块不同的内存空间,所以需要变量来使内存可以重复利用。
数据在计算机的存储
数值:
二进制、最小单元是字节(8bit)
文本:
字符-》ASCII码-》数值
图片:
像素点-》三个颜色-》数值
声音:
波形图-》数值
数据类型
基本数据类型
引用数据类型
变量存放地址
数组
类
接口
详细见下面的一级标题
类型转换
自动类型转换
- 类型范围小的变量可以直接赋值给类型范围大的变量
byte a = 11;
int b = a;
- 表达式中,小范围类型变量转换为较大范围类型变量,然后再参与计算
- 表达式结果的类型由最高类型决定
- byte short char直接转换为int参与运算,直接转化为int 就算是byte+byte也是(害怕越界)
强制类型转换
大范围类型变量不可以直接赋值给小范围类型变量
- 强转可能会导致数据的丢失(溢出)
- 浮点数转换为整数的时候,直接丢掉小数部分,保留整数部分
运算符
运算符:一种特殊符号,用以表示数据的运算、赋值和比较数与整数
运算符分类:算术运算符、赋值运算符、比较运算符、逻辑运算符、三元运算符
算术运算符
+与字符串运算的时候充当连接符,结果依旧是一个字符串
“abc”+11 = “abc11” 能算则算,不能算则连接
++ 只能操作变量,不能用于字面量
赋值运算符
=是从右向左看的
下面的都是存在强制类型转换的
比较运算符
逻辑运算符
Java中,& | 无论左边是false还是true 右边都是要执行的
三元运算符
条件表达式?值1:值2
条件表达式为true则返回值1,为false则返回值2
运算符优先级
java输入
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
//1、导包:idea自动导包
//2、得到一个键盘扫描类对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户年龄");
//3、调用sc的功能,来接受int类型
int age = sc.nextInt();//等待用户输入一个int 直到用户按下了回车键才会拿到数据
System.out.println("请输入用户名字");
String name = sc.next();
System.out.println("用户:"+name + age);
}
}
流程控制
顺序 选择 循环
选择结构
- Java的switch中的表达式只能是 byte short int char,JDK5开始支持枚举,JDK7开始支持string,不支持double、float。、long
- case后面的值不可以重复,只能是字面量
循环结构
for
while
do while
死循环
break和continue
- break:跳出本次循环
- continue:结束本次循环的当前执行
break只能用于循环和switch
continue只能用于循环
数组
数组是数据的集合,一个容器,用来存储任何类型的数据,包括原始数据类型和引用数据类型,但是一旦指定了数组的类型之后,就只能用来存储指定类型的数据。
定义数组
静态初始化数组
定义数组的时候直接给数组赋值
注意:
- 数据类型[] 数组名 === 数据类型 数组名[]
- 什么类型的数组只能存放什么类型的数据(自动类型转换)
动态初始化数组
定义数组的时候先不存入具体的元素值,仅确定数组存储的数据类型和数组长度
数组声明其长度后不可改变
注意:静态和动态初始化数组是独立的,不可以混用
动态初始化数组元素默认值规则
访问
二维数组
数组变量的声明:
语法: 数据类型[][] 数组名;
,如:int[][] num;
、double[][] d;
、String[][] str
;
数组对象的创建:
语法:数组名 = new 数据类型[外长度][内长度];
,如:num = new int[4][3];
,数组声明其长度后不可改变
赋值:
语法:数组名[外下标][内下标] = 数据;
,如:num[0][0]= 3;
数组元素的使用及遍历:
语法:数组名[外下标][内下标]
,获取指定下标是数据。
方法
概述
方法是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用
好处:
- 提高代码的复用性,提高开发效率
- 让程序的逻辑更清晰
注意点
- 方法在类中位置无所谓,但是不能在方法里面定义方法
- 返回类型为void 不需要return ,返回值类型为具体类型,return必须是该类型
- return下面不能编写代码
- 方法不调用就不会执行,方法传参严格按照形成类型
参数传递机制
Java的参数传递机制都是:值传递
传输的是实参变量中存储的值的副本
基本类型的参数传递
引用类型的参数传递
方法重载
一个类中,可以出现多个重名的方法,但是他们的形参列表不同,那么这些方法就称为方法重载
只要是名称相同、形参列表不同(形参的个数、类型、顺序),那么就是方法重载。其他的都不管(修饰符、返回值类型无所谓)
面向对象
五大成员:变量、方法、构造器、内部类、代码块
封装 继承 多态
类:对象的设计图(对象的模板)
对象:本质是一种特殊的数据结构
一个代码文件中,可以写多个class类,但是只能有一个public而且必须修饰代码文件名
构造器
创建对象的时候自动调用构造器
- 如果不写构造器,编译器自动生成一个无参构造器
- 如果定义了有参数构造器,那么编译器不会自动生成无参构造器
- (和C++class相同)
this
this就是变量,用于方法中拿到当前对象(哪个对象调用方法,this就指向该对象)
应用场景:解决变量名称冲突的问题
封装
封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作[方法],才能对数据进行操作。
合理隐藏 合理暴露
好处:
(1)只能通过规定的方法访问数据
(2)隐藏类的实例细节,方便修改和实现。
实体类
一种特殊形式的类:
- 成员都是私有的,提供getter和setter
- 必须有一个公共无参构造函数
只负责数据存取,而对数据的处理交给其他类来完成,以实现数据和数据业务处理相分离。
实体类
package javabean;
public class Student {
private String name;
private int age;
public Student(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;
}
}
static关键字
静态,可以修饰成员变量和成员方法
类变量和实例变量
**应用场景:**如果某个数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义成类变量来记住
比如说,我们想要知道一个类有多少对象那么就用到static
成员变量的执行原理
类方法和实例方法
成员方法的执行原理
类方法最常见的就是做工具类(类内的方法都是类方法)
- 因为创建对象会占用内存,导致浪费内存
- 提高了代码复用 使用方便 提高了开发效率
- 工具类没有必要创建对象,那么可以将构造器设为私有
注意事项
- 类方法中不可以直接访问实例成员,只可以访问类成员
- 实例方法既可以直接访问实例成员,又可以直接访问类成员
- 实例方法中可以出现this,类方法中不可以出现this
应用知识:代码块
代码块在实际开发的时候用处不大,主要是看源码的时候用得到
分为静态代码块和实例代码块
静态代码块
- 格式:
static{}
- 特点:类加载(加载到方法区,只要写class就会加载)时自动执行,类只会加载一次所以静态代码块也只会执行一次
- 作用:完成类的初始化,例如对静态成员进行初始化赋值
public class Student {
static int age;
static {
System.out.println("静态代码块");
age=50;
}
}
public class Test {
public static void main(String[] args) {
System.out.println(Student.age);
System.out.println(Student.age);
}
}
实例代码块
- 格式:
{}
- 特点:每次创建对象的时候,执行实例代码块,在构造器前执行
- 作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值
public class Test {
public static void main(String[] args) {
System.out.println(Student.age);
System.out.println(Student.age);
System.out.println("-----------------------");
Student s1 = new Student();
Student s2 = new Student("hello");
}
}
public class Student {
String name;
static int age;
//静态代码块
static {
System.out.println("静态代码块");
age = 50;
}
//实例代码块
{
System.out.println("实例代码块");
}
public Student() {
System.out.println("无参数构造器");
}
public Student(String name) {
this.name = name;
System.out.println("有参数构造器");
}
}
应用知识:单例设计模式
什么是设计模式?
一个问题通常有n种解法,其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
设计模式有20多种,对应20多种软件开发中会遇到的问题。
单例设计模式:一个类只能有一个对象
饿汉式单例写法:在获取对象的时候,对象已经提前创建好了
- 构造器私有
- 定义一个类变量记住类的一个对象
- 定义一个类方法返回对象
//由于a是类成员 所以只有在类加载的时候创建一下
//所有后续无论调用多少次getObject类方法都是返回的同样的a地址
public class A {
private static A a = new A();
private A(){}
public static A getInstance(){
return a;
}
}
懒汉式单例写法:在获取对象的时候,对象才会被创建
- 构造器私有
- 定义一个类变量记住类的一个对象
- 定义一个类方法返回对象
public class B {
private static B b;
private B(){}
public static B getInstance(){
if (b==null)b=new B();
return b;
}
}
单例设计模式的应用场景和好处:
runtime类、电脑任务管理器
继承
基本
关键字**extends
**
子类继承父类所有的非私有的成员
子类的对象是由父类和子类共同完成的
public class B extends A{}
//B 派生类 A 基类
权限修饰符
private 缺省 protected public
- public:任意类都可以访问
- private:只能在本类访问
单继承
- java与C++不同,Java仅支持单继承,即一个类只能继承一个直接父类;但是支持多层继承
Object
是所有类的祖先
class A{}//等价于 class A extends Object{}
方法重写
当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写
重写的注意事项:
- 重写后,方法的访问,Java会遵循就近原则
- 子类重写父类方法的时候,访问权限必须大于等于父类方法的权限(public>protected>缺省)
- 私有、静态方法不能重写
- 使用
@Override
,可以检查我们方法重写的格式是否正确,代码可读性也更好 - 重写的方法返回值类型必须与被重写的方法的返回值类型一样,或者范围更小
但是我们使用的时候一般就是 声明不变,重新实现
应用场景:重写Object的toString()方法
public class A {
private String name;
private int age;
public A(){}
public A(String name,int age){
this.name=name;
this.age=age;
}
@Override
public String toString(){
return "name="+name+",age="+age;
}
}
不重写
重写
子类访问其他成员
public class Test {
public static void main(String[] args) {
Son s = new Son();
s.print();
}
}
class Fater{
String name="父类名字";
}
class Son extends Fater{
String name = "子类名字";
void print(){
String name = "局部名称";
System.out.println(name);//局部
System.out.println(this.name);//本类
System.out.println(super.name);//父类
}
}
就近原则
子类构造器
特点
子类的全部构造器,都会调用父类的构造器然后再调用自己
默认情况下,子类全部构造器第一行都是为super()
,这个就是调用父类的无参构造器
如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(...)
,指定去调用父类的有参数构造器
一个类的任意构造器中,我们可以通过this(...)
去调用该类的其他构造器
一个构造器中不能同时有this()
和super()
应用场景
public class Test {
public static void main(String[] args) {
Teacher t = new Teacher("李梅",36,"Java C++");
}
}
class Person{
private String name;
private int age;
Person(){}
Person(String name,int age){
this.name=name;
this.age=age;
}
}
class Teacher extends Person{
private String skill;
Teacher(){}
Teacher(String name,int age,String skill){
super(name,age);
this.skill=skill;
}
Teacher(String name,int age){
this(name,age,"打豆豆");
}
}
多态
概念
多态是在继承/实现情况下的一种现象,表现为:对象多态、行为多态
People p = new Student();
People p = new Teacher();
//人即可能是学生有可能是老师
前提:
- 有继承/实现关系
- 存在父类引用子类对象
- 存在方法重写
注意:多态是对象、行为的多态,Java中的成员变量不谈多态
public class Test {
public static void main(String[] args) {
Person p1 = new Teacher();
p1.print();//I am teacher 方法:编译看左边 运行看右边
System.out.println(p1.name);//person 变量:编译看左边 运行看左边
}
}
class Person{
public String name = "person";
void print(){
System.out.println("I am person");
}
}
class Teacher extends Person{
public String name = "teacher";
@Override
void print(){
System.out.println("I am teacher");
}
}
好处
- 右边对象是解耦合的,便于扩展和维护
- 使用父类类型的形参可以接受一切子类对象,扩展性更强、更便利
缺点
多态下不能直接使用子类独有的功能
解决方式强制类型转换
- 自动类型转换:
父类 变量名=new 子类
- 强制类型转换:
子类 变量名=(子类)父类变量
强制类型转换注意点:
- 存在继承/实现时,就可以进行强制类型转换,编译阶段不会报错。
- 但是,运行时,如果发现对象的真实类型与强转后的类型不同会报错(ClassCastException)
**建议:**使用 instanceof
判断当前对象的真实类型
public class Test {
public static void main(String[] args) {
Person p1 = new Teacher();
p1.print();
// Teacher t1 = (Teacher) p1;//编译不报错
// t1.teacher();
//
// Student s1 = (Student) p1;//编译不报错 运行报错 真实类型不匹配 ClassCastException
//建议使用
if (p1 instanceof Teacher){
Teacher t1 = (Teacher) p1;//编译不报错
t1.teacher();
}else{
Student s1 = (Student) p1;
s1.test();
}
}
}
class Person {
public String name = "person";
void print() {
System.out.println("I am person");
}
}
class Teacher extends Person {
public String name = "teacher";
@Override
void print() {
System.out.println("I am teacher");
}
void teacher() {
System.out.println("teaching~~");
}
}
class Student extends Person {
public String name = "Student";
@Override
void print() {
System.out.println("I am Student");
}
void test() {
System.out.println("test~~");
}
}
final关键字
final是最终的意思,可以修饰 类 方法 变量
- 修饰类:类不能被继承
- 修饰方法:方法不能被重写
- 修饰变量:变量只能被赋值一次(类似于const)
- 局部变量
- 成员变量
- 静态成员变量
- 实例成员变量
final修饰变量
- final修饰基本类型的变量,变量存储的数据不能被改变
- final修饰引用类型的变量,变量存储的地址不能被改变,但地址所指向对象的内容是可以被改变的
常量(单词大写,下划线隔开)
static final
修饰的成员变量- 程序编译的时候,常量会被宏替换:出现常量的地方全部会被替换为被记住的字面量,使用常量和字面量性能是一样的
抽象类
概述
abstract
关键字,修饰类是抽象类,修饰方法是抽象方法
注意点
- 抽象类中不一定有抽象方法,有抽象方法的一定是抽象类
- 抽象方法没有函数体,只有函数声明
- 类该有的成员(成员变量、方法、构造器)抽象类都可以有
- 抽象类不可以实例化对象,仅作为一个父类让子类继承
- 一个类继承抽象类,必须重写所有的抽象方法,否则这个类也要定义为抽象类
好处
父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们设计这样的抽象类,就是为了更好的支持多态,
public class Test {
public static void main(String[] args) {
Animal animal = new Dog("kitt");
animal.cty();
animal=new Cat("xixi");
animal.cty();
}
}
abstract class Animal{
private String name;
Animal(){}
Animal(final String name){
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
abstract public void cty();
}
class Dog extends Animal{
Dog(){}
Dog(final String name){
super(name);
}
@Override
public void cty() {
System.out.println(getName()+"=wang-wang-wang~~");
}
}
class Cat extends Animal{
Cat(){}
Cat(final String name){
super(name);
}
@Override
public void cty() {
System.out.println(getName()+"=miao-miao-miao~~");
}
}
场景:模板方法设计模式
解决的问题:方法中存在重复代码的问题
写法:
- 定义一个抽象类
- 在里面定义两个方法,一个是模板方法:放相同的代码里,一个是抽象方法:具体实现交给子类完成
模板方法建议final
修饰
package oop_abstract;
public class Test {
public static void main(String[] args) {
/**
* 猫和狗都有一个叫
* 第一句和最后一句都是一样的 中间的叫不一样
*/
Dog d = new Dog();
d.cry();
Cat c = new Cat();
c.cry();
}
}
abstract class Animal{
//模板方法禁止重写(专业一些)
public final void cry(){
System.out.println("开始了");
System.out.println(selfC());
System.out.println("结束了");
}
abstract String selfC();
}
class Dog extends Animal{
@Override
String selfC() {
return "wang";
}
}
class Cat extends Animal{
@Override
String selfC() {
return "miao";
}
}
接口
简述
关键字interface
public interface 接口名{
//只能有变量和方法,不能有其他成员
//变量 -> 常量
//方法 -> 抽象方法
}
接口不能创建对象,是用来**被类实现(implements)**的,实现接口的类称为实现类
修饰符 class 实现类 implements 接口1,接口2...{}
一个类可以实现多个接口,实现类必须重写所有接口的所有抽象方法
public class Test {
public static void main(String[] args) {
T t = new T();
t.printA();
}
}
class T implements A,B{
@Override
public void printA() {
System.out.println("helloA");
}
@Override
public void printB() {
System.out.println("helloB");
}
}
interface A{
//默认常量
String SCHOOL_NAME="XUPT";
//默认抽象方法
void printA();
}
interface B{
//默认常量
String SCHOOL_NAME="XUPT";
//默认抽象方法
void printB();
}
好处
- 弥补了类单继承的不足,一个类同时可以实现多个接口
- 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
ClassManager cm = new ClassManager();
cm.printInfo();
cm.printScore();
}
}
class ClassManager {
private ArrayList<Student> students = new ArrayList<>();
private StudentOperator studentOperator = new StudentOperatorImpl2();//只需要更改这里就可以修改功能
public ClassManager() {
students.add(new Student("古力娜扎", '女', 82.5));
students.add(new Student("迪丽热巴", '女', 72.5));
students.add(new Student("八嘎亚历", '男', 85.65));
students.add(new Student("玛卡巴卡", '男', 92.5));
students.add(new Student("无锡碧玺", '男', 62.5));
students.add(new Student("吴京", '男', 78.5));
}
public void printInfo() {
studentOperator.printAllInfo(students);
}
public void printScore() {
studentOperator.printScore(students);
}
}
//全部信息 + 平均分
class StudentOperatorImpl1 implements StudentOperator {
@Override
public void printAllInfo(ArrayList<Student> students) {
System.out.println("====================");
for (Student student : students) {
System.out.println(student.getName() + "-" + student.getScore());
}
System.out.println("====================");
}
@Override
public void printScore(ArrayList<Student> students) {
double score = 0;
for (Student student : students) {
score += student.getScore();
}
System.out.println(score/students.size());
}
}
//全部信息男女人数 + 平均分去掉最大最小
class StudentOperatorImpl2 implements StudentOperator {
@Override
public void printAllInfo(ArrayList<Student> students) {
System.out.println("====================");
int count1 = 0, count2 = 0;
for (Student student : students) {
System.out.println(student.getName() + "-" + student.getScore());
if (student.getSex()=='男')
count1++;
else
count2++;
}
System.out.println("男生人数:"+count1);
System.out.println("女生人数:"+count2);
System.out.println("总人数:"+students.size());
System.out.println("====================");
}
@Override
public void printScore(ArrayList<Student> students) {
double score = 0;
double max = students.get(0).getScore(), min = students.get(0).getScore();
for (Student student : students) {
max = Math.max(max,student.getScore());
min = Math.min(min,student.getScore());
score += student.getScore();
}
System.out.println((score-max-min)/(students.size()-2));
}
}
interface StudentOperator {
void printAllInfo(ArrayList<Student> students);
void printScore(ArrayList<Student> students);
}
class Student {
private String name;
private char sex;
private double score;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public Student() {
}
public Student(String name, char sex, double score) {
this.name = name;
this.score = score;
this.sex = sex;
}
}
JDK8之后接口新特性
public interface A{
default void test1(){
/*
默认public 使用default修饰
只能使用接口的类实现对象调用
*/
}
static void test2(){
/*
静态方法 默认public
只能使用接口名调用
*/
}
private void test3(){
/*
JDK9之后支持
接口内部调用
*/
}
}
- 增强接口本身能力,便于项目的扩展和维护
接口多继承
一个接口可以同时继承多个接口
便于实现类的实现
interface A{}
interface B{}
interface C extends A,B{}
注意事项
-
接口多继承:存在方法名冲突,不支持多继承
-
类多实现接口:存在方法名冲突,不支持多实现
-
一个类继承父类,又同时实现了接口,父类和接口中存在方法名冲突,优先调用父类的方法
class F{
public void run(){
System.out.printIn("fu");
}
}
interface A{
public void run(){
System.out.printIn("A");
}
}
class Z extends F implements A{}
Z z = new Z();
z.run();//fu
- 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
interface A{
public void run(){
System.out.printIn("A");
}
}
interface B{
public void run(){
System.out.printIn("B);
}
}
class C implements A,B{
@Override
public void run(){}//不报错
}
内部类
当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
成员内部类
就是类中的一个普通成员,类似前面我们学过的普通的成员变量、成员方法
public class Innter {
public static void main(String[] args) {
Outer.Inner in = new Outer().new Inner();//创建对象
in .test();
}
}
class Outer{
private int a=1;
class Inner{
public static String name; //JDK 16之后才支持定义静态成员
private int a=2;
Inner(){}
public void test(){
int a = 3;
System.out.println(a);
System.out.println(this.a);
System.out.println(Outer.this.a);//可以访问外部类的成员
}
}
}
静态内部类
static修饰的内部类,所属外部类自己持有
public class Innter {
public static void main(String[] args) {
Outer.Inner in = new Outer.Inner();
in.test();
}
}
class Outer{
private int a = 1;
//可以访问外部类的静态成员 不能直接访问实例成员
static class Inner{
public int age;
public static String name; //JDK 16之后才支持定义静态成员
private int a=2;
Inner(){}
public void test(){
int a = 3;
System.out.println(a);
System.out.println(this.a);
}
}
}
局部内部类
定义在方法中、代码块中、构造器等
鸡肋语法
匿名内部类
重点
特殊的局部内部类;不需要声明类的名字
本质就是一个子类,会立刻创建一个对象
方便创建一个子类对象
public class Innter {
public static void main(String[] args) {
/**
一个子类 立即创建一个对象
*/
Animal dog = new Animal() {
@Override
public void cry() {
System.out.println("汪汪汪");
}
};
dog.cry();
}
}
abstract class Animal{
public abstract void cry();
}
应用场景
作为一个参数传输给方法
public class Innter {
public static void main(String[] args) {
go(new Animal() {
@Override
public void run() {
System.out.println("🐕在run");
}
});
}
private static void go(Animal a){
a.run();
}
}
interface Animal{
void run();
}
GUI的应用
import javax.swing.*;
import java.awt.event.ActionEvent;
public class Main {
public static void main(String[] args) {
JFrame win = new JFrame("登录页面");
JPanel panel = new JPanel();
win.add(panel);
JButton but = new JButton("登录");
win.add(but);
// 简化代码 AbstractAction接口的一个实现类 重写actionPerformed
but.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(win,"登录一下");
}
});
win.setSize(400,400);
win.setLocationRelativeTo(null);
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
win.setVisible(true);
}
}
枚举
认识枚举
枚举是一个特殊的类
格式
修饰符 enum 枚举类型{
名称1,名称2,...;
其他成员;
}
package Enum;
public class Test {
public static void main(String[] args) {
A a = A.X;
System.out.println(a);
}
}
enum A{
//枚举类第一行必须罗列枚举对象的名字,这些名称都是常量,每个常量都是枚举类的一个对象
X,Y,Z;
//枚举类的构造器是私有的 写不写都是私有的
//枚举类是最后的 不能被继承
//提供一些额外的API values valueOf name ordinal
}
抽象枚举
抽象类不可以实例化对象,但是枚举在内部的第一行是实例化对象的 所以要重写抽象方法
public enum B{
X(){
@Override
public void run() {
System.out.println("running");
}
},Y("张三"){
@Override
public void run() {
System.out.println(getName()+"running");
}
};
private String name;
B() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
B(String name) {
this.name = name;
}
public abstract void run();
}
可以实现单例设计模式
public enum A{
X;
}
应用场景
用来表示一组信息,然后作为参数进行传输
选择定义一个一个的常量来表示一组信息,并作为参数传输:参数值不受约束。
选择定义枚举表示一组信息,并作为参数传输:代码可读性好,参数值得到了约束,对使用者更友好,建议使用!
泛型
认识泛型
定义类、方法、接口时,同时声明了一个或者多个类型变量<E>
,称为泛型类、泛型方法、泛型接口,统称泛型
作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力!这样可以避免强制类型转换,及其可能出现的异常。
泛型的本质:把具体的数据类型作为参数传给类型变量。
泛型类
模板
修饰符 class 类名<类型变量1,...>{}
package String;
public class array<E> {
private Object[] arr= new Object[10];//Object是所有类的父类
private int length;
public boolean add(E e) {
arr[length++] = e;
return true;
}
public E get(int index) {
return (E) arr[index];//强制类型转换
}
public int size() {
return length;
}
}
class Dog<T extends Animal>{}T 只能是Animal或者其子类
泛型接口
模板
修饰符 interface 接口名<类型变量1,...>{}
public interface Data<T extends Animal>{//T 只能是Animal或者其子类
void add(T t);
ArrayList<T>get(String name);
}
泛型方法
模板
修饰符 <类型变量1,...> 返回值类型 方法名(形参列表){}
import java.util.ArrayList;
public class Car {
public static void main(String[] args) {
}
// public static <T> int count(ArrayList<T> t){
// return 5;
// }
//?是个泛型通配符 接受所有的类型
//对其限制 ? extends car(car以及其子类 上限是car)
// ? super car(car以及其父类 下限是car)
public static int count(ArrayList<?> t) {
return 1;
}
}
泛型通配符:?
注意事项
- **泛型擦除:**泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中不存在泛型
- 泛型不支持基本基本数据类型,仅支持引用数据类型
常用API
API应用程序编程接口 别人写好的轮子
包
包:用来分类的管理各种不同程序,类似文件夹,建包有利于程序的管理和维护
注意事项
- 同一个包下的类可以直接访问
- 调用其他包下的程序,必须导包(import 导包)
- 如果当前程序中,要调用]ava提供的程序,也需要先导包才可以使用;但是java.lang下的不需要导包,可以直接使用
- 如果当前程序中,要调用多个不同包下的程序,而这些程序名正好一样,此时默认只能导入一个程序,另一个程序必须带包名访问。
String
java.lang.String
常用构造器
直接赋值
或者
常用方法
package String;
public class test {
public static void main(String[] args) {
String n = "hello yb0os1";
//长度
System.out.println(n.length());
//根据索引获取字符
System.out.println(n.charAt(6));
//字符串转化为字符数组
char[] s = n.toCharArray();
for (int i = 0; i < s.length; i++) {
System.out.print(s[i]+" ");
}
System.out.println();
//判断字符串内容是否相同 大小写敏感
String n1 = new String("hello yb0os1");
String n2 = new String("hello yb0os1");
System.out.println(n1==n2);
System.out.println(n.equals(n2));
//判断字符串内容是否相同 大小写不敏感
String c1="34Af7";
String c2="34af7";
System.out.println(c1.equalsIgnoreCase(c2));
//截取字符串内容 [beg,end)
String mainS = "我是最好的编程语言";
System.out.println(mainS.substring(0,5));//[0,5)
System.out.println(mainS.substring(5));//[5,结尾)
//替换字符串
String info = "你真是一个大垃圾啊 垃圾东西";
String re = info.replace("垃圾","**");
System.out.println(re);
//判断字符串中是否包含某个关键字 大小写敏感
String ss = "java Jasda";
System.out.println(ss.contains("java"));
//判断字符是否以某个字符开头 大小写敏感
String rs1 = "Java";
System.out.println(rs1.startsWith("J"));
System.out.println(rs1.startsWith("ja"));
//分割字符串 放入字符串数组中
String[] res = "张无忌 武警 吴京 赵敏 殷素素".split(" ");
for (int i = 0; i < res.length; i++) {
System.out.println(res[i]);
}
}
}
注意事项
-
string是不可变对象
-
双引号(就是隐式的调用new String(“字符串”))写出的字符串对象是放在字符串常量池里面,且相同的字符串只存储一份
-
new出来的字符串对象,每new一次都会产生一个新对象存放着堆内存中
String s1=String("a");//创建两个对象 一个在字符串常量池里面 一个在堆内存
String s2 = "a"; //创建0个对象
变量的运算是放在堆里面的
案例
验证码
import java.util.Random;
public class Code {
public static String codes = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static void main(String[] args) {
String code = getCodes(5);
System.out.println(code);
}
public static String getCodes(int n){
Random r = new Random();
StringBuilder code= new StringBuilder();
for (int i = 0; i < n; i++) {
code.append(codes.charAt(r.nextInt(codes.length())));
}
return code.toString();
}
}
简单登录
import java.util.Scanner;
public class Login {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; ++i) {
System.out.print("请输入账号:");
String name = sc.next();
System.out.print("请输入密码:");
String password = sc.next();
if (name.equals("yb0os1") && password.equals("123456")) {
System.out.println("欢迎进入系统");
break;
} else {
System.out.println("错误~~ 重新输入");
}
}
}
}
ArrayList
一种最常用的集合
常用构造器
常用方法
注:倒数第二个方法只删除第一个位置出现的o
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();//可以存储任意类型的数据
list1.add(1);
list1.add("he");
System.out.println(list1);
ArrayList<String>list2=new ArrayList<>();//只能存储String
list2.add("yb0os1");
list2.add("hello");
list2.add(1,"wochadui");
System.out.println(list2);
}
}
案例
边遍历边删除存在一些小问题
import java.util.ArrayList;
public class DeleteAllTarget {
public static void main(String[] args) {
//集合中找数据并且删除
//如果直接删除会导致bug 删除不干净
ArrayList<String>list=new ArrayList<>();
list.add("枸杞");
list.add("C++");
list.add("Java");
list.add("yb0os1");
list.add("Python");
list.add("红枸杞");
list.add("黑枸杞");
/* for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if (s.contains("枸杞")){
list.remove(s);
--i;//解决bug方法一:每次删除就回退一个单位
}
}*/
//解决bug方法二:从后向前遍历删除
for (int i = list.size()-1; i >=0 ; i--) {
String s = list.get(i);
if (s.contains("枸杞"))list.remove(i);
}
System.out.println(list);
}
}
Object类
Object是所有类的祖宗类 所有类都可以使用Object提供的方法
常见方法
import java.util.Objects;
public class _Object_ {
public static void main(String[] args) throws CloneNotSupportedException {
Student stu1 = new Student("李四",18);
//toString存在的意义是被重写的直接输出对象==对象.toString()
System.out.println(stu1);
Student stu2 = new Student();
//equals默认判断内存地址是否相同 存在的意义也是被重写 判断内容
System.out.println(stu1.equals(stu2));
//clone是protected的 所以不同包下的文件的对象不可以直接访问 要在类中重写 然后类还要实现Cloneable
//clone默认是浅克隆 引用数据类型拷贝的是地址 而不是新的
Student stu3 = (Student) stu1.clone();
}
}
//Cloneable是一个标记接口 实现了才能clone
class Student implements Cloneable{
private String name;
private int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
//浅克隆 调用父类的
return super.clone();
}
@Override
public boolean equals(Object obj) {
if (this == obj)return true;
//为空 或者 类型不同 直接false
if (obj==null || this.getClass()!=obj.getClass())return false;
return this.getAge() == ((Student) obj).getAge() && Objects.equals(this.getName(),((Student)obj).getName());
}
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 Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
浅克隆 深克隆
Objects类
一个工具类 提供了很多操作对象的静态方法
常见方法
在Object
子类重写equals
比较字符串的时候 为什么使用Objects.equals
而不是String
的equals
?
因为如果使用String的 当调用者是null的时候报错 而Objects的不会有这个问题
import java.util.Objects;
public class _Objects_ {
public static void main(String[] args) {
String name1 = null;
String name2="yb0os1";
System.out.println(Objects.equals(name1,name2));
// System.out.println(name1.equals(name2));//报错 NullPointerException
System.out.println(Objects.isNull(name1));//等价 name1 == null 内部就是这样实现的
System.out.println(Objects.nonNull(name1));//等价 name1 != null 内部就是这样实现的
}
}
//Objects的equals的源码如下,所以他更加安全
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
包装类
把基本数据类型包装成对象
Integer
为例子
import java.util.ArrayList;
public class _Integer_ {
public static void main(String[] args) {
Integer i = new Integer(5);//已经废除
Integer j = Integer.valueOf(5);
//自动装箱:可以自动把基本类型的数据转换成对象。
Integer k = 5;
//自动拆箱:可以自动把包装类型的对象转换成对应的基本数据类型
int l = k;
ArrayList<Integer> intArr = new ArrayList<>();
intArr.add(15);//自动装箱
int rs = intArr.get(0);//自动拆箱
System.out.println("------------------------");
//基本类型数据转化为字符串
Integer a = 50;
String rs1 = Integer.toString(a);
String rs2 = a.toString();//继承的Object
System.out.println(rs1 + 1);
System.out.println(rs2 + 1);
//字符串类型转化为基本数据类型
String ageStr = "19";
// int age = Integer.parseInt(ageStr);
int age = Integer.valueOf(ageStr); // 推荐这个 只需要记一个
System.out.println(age + 1);
String scoreStr = "99.5";
// double score = Double.parseDouble(scoreStr);
double score = Double.valueOf(scoreStr);
System.out.println(score + 0.65);
}
}
StringBuilder
类
可变字符串对象,用来操作字符串的
StringBuilder
比String
更适合做字符串的修改操作,效率更高 代码更简洁
常用方法
public class _StringBuilder_ {
public static void main(String[] args) {
StringBuffer s = new StringBuffer("yb0os1");
//拼接:几乎支持所有的类型
s.append(12);
s.append(3.14);
s.append(true);
s.append("y");
s.append(new Object());
System.out.println(s);
//append支持链式编程
s=new StringBuffer();
s.append(1).append(2).append(3).append("!点火~~");
System.out.println(s);
//翻转:直接在自身修改
s.reverse();
System.out.println(s);
//长度
System.out.println(s.length());
//StringBuilder转换为String
String rs = s.toString();
System.out.println(rs);
}
}
为什么操作字符串推荐使用StringBuilder
而不是String
?
效率更高
- 频繁的拼接、修改建议
StringBuilder
- 其余建议
String
StringBuffer
类
和StringBuilder
用法一模一样
区别
StringBuilder
是线程不安全的,StringBuffer
是线程安全的
StringJoiner
类
import java.util.StringJoiner;
public class _StringJoiner_ {
public static void main(String[] args) {
//间隔, 开始[ 结束]
StringJoiner s = new StringJoiner(", ","[","]");
//只能加入字符串
s.add("yb0os1");
s.add("hello");
System.out.println(s);
}
}
Math类
数学工具类:静态方法
常用方法
public class _Math_ {
public static void main(String[] args) {
//abs可传入int double 返回正数
System.out.println(Math.abs(-55));
System.out.println(Math.abs(-5.5));
//ceil 向上取整 返回的double
System.out.println(Math.ceil(4.01));
System.out.println(Math.ceil(-2.5));
//floor 向下取整 返回的double
System.out.println(Math.floor(4.01));
System.out.println(Math.floor(-2.5));
//round 四舍五入 返回的long
System.out.println(Math.round(4.01));
System.out.println(Math.round(-2.5));
//max min
//pow 取次方 double
System.out.println(Math.pow(2,3));//2^3
//random 去随机数 默认[0.0,1.0)
System.out.println(Math.round(Math.random()*10));
}
}
System类
系统工具类:静态方法
public class _System_ {
public static void main(String[] args) {
/**
* 终止当前运行的Java虚拟机
* 非0代表异常终止
* 0代表正常终止
*/
// System.exit(0);//(不建议使用)
// System.out.println(11);//执行不到了
/***
* 获取当前系统时间 返回的是long
* 毫秒值:从1970-1-1 0:0:0开始到此刻的毫秒值
* 可以用于性能分析
*/
long time = System.currentTimeMillis();
// System.out.println(time);
for (int i = 0; i < 10000; i++) {
System.out.println("dassssssssssssssssssssssssssssssssssssssssss");
}
long timenew = System.currentTimeMillis();
System.out.println((timenew-time)+"ms");
}
}
Runtime类
程序运行的运行环境
单例类
import java.io.IOException;
public class _Runtime_ {
public static void main(String[] args) throws IOException, InterruptedException {
//获取当前java应用程序关联的运行对象
Runtime r = Runtime.getRuntime();
//终止当前虚拟机
// r.exit(0);
//获取虚拟机能够使用的处理器数
System.out.println(r.availableProcessors());
//返回java虚拟机中内存总量 long 字节
System.out.println(r.totalMemory()/1024.0/1024.0+"MB");
//返回java虚拟机中可用内存量
System.out.println(r.freeMemory()/1024.0/1024.0+"MB");
//启动某个程序 并返回代表该程序的对象 Process 类型
Process p = r.exec("D:\\XJad\\XJad\\XJad.exe");
Thread.sleep(5000);
p.destroy();
}
}
BigDecimal
类
用的多
解决浮点数运算时出现结果失真的情况
不要使用BigDecimal(double val)
import java.math.BigDecimal;
import java.math.RoundingMode;
public class _BigDecimal_ {
public static void main(String[] args) {
double a = 0.1;
double b = 0.3;
System.out.println(a+b);
System.out.println("--------------------");
// BigDecimal c = new BigDecimal(Double.toString(a));
// BigDecimal d = new BigDecimal(Double.toString(b));
//等价
BigDecimal c = BigDecimal.valueOf(a);
BigDecimal d = BigDecimal.valueOf(b);
System.out.println(c.add(d));
System.out.println(c.subtract(d));
System.out.println(c.multiply(d));
//向上取 2为小数
System.out.println(c.divide(d,2, RoundingMode.HALF_UP));
double rs = c.doubleValue();
System.out.println(rs);
}
}
JDK8之前传统的日期、时间类
Date
import java.util.Date;
public class _Date_ {
public static void main(String[] args) {
Date date = new Date();
//系统时间信息
System.out.println(date);
//时间毫秒值
long time = date.getTime();
System.out.println(time);
//时间毫秒值转换为系统时间信息
time+=10*1000;
Date d = new Date(time);
System.out.println(d);
}
}
SimpleDateFormat
简单时间格式化
时间格式
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class _SimpleDateFormat_ {
public static void main(String[] args) throws ParseException {
Date d = new Date();
long time = d.getTime() + 5 * 1000;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a");
System.out.println(sdf.format(d));
System.out.println(sdf.format(time));
System.out.println("----------------------------");
//字符串时间称为日期对象
String dataStr = "2024-5-19 13:14:00";
//创建简单日期格式化对象 时间格式必须和字符串的相同
SimpleDateFormat sdatef = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d2 = sdatef.parse(dataStr);
System.out.println(d2);
}
}
简单的使用
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class _MiaoSha {
private final static String BEGIN = "2023年11月11日 0:0:0";
private final static String END = "2023年11月11日 0:10:0";
public static void main(String[] args) throws ParseException {
String Jia = "2023年11月11日 0:01:18";
String Pi = "2023年11月11日 0:10:51";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date dJia = sdf.parse(Jia);
Date dPi = sdf.parse(Pi);
Date begin=sdf.parse(BEGIN);
Date end=sdf.parse(END);
long timeBeg = begin.getTime();
long timeEnd = end.getTime();
long timePi = dPi.getTime();
long timeJia = dJia.getTime();
if (timePi>=timeBeg&&timePi<=timeEnd){
System.out.println("小皮秒杀成功,还剩下"+(timeEnd-timePi)/1000.0+"s");
}else{
System.out.println("小皮秒杀失败,超出"+(timePi-timeEnd)/1000.0+"s");
}
if (timeJia>=timeBeg&&timeJia<=timeEnd){
System.out.println("小贾秒杀成功,还剩下"+(timeEnd-timeJia)/1000.0+"s");
}else{
System.out.println("小贾秒杀失败,超出"+(timeJia-timeEnd)/1000.0+"s");
}
}
}
Calendar
抽象类
代表系统此刻时间对应的日历
通过它可以单独的修改年月日时分年
可变对象,都是在原对象的基础上进行改动的
import java.util.Calendar;
import java.util.Date;
public class _Calendar_ {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
// System.out.println(c);
//获取日历的某个信息
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH));//月份从0开始计算的
//拿到日历的日期对象
Date d = c.getTime();
System.out.println(d);
//拿到时间毫秒值
long time = c.getTimeInMillis();
System.out.println(time);
//修改日历的某个信息
c.set(Calendar.MONTH,4);
System.out.println(c.get(Calendar.MONTH));
//为某个信息加/减多少
c.add(Calendar.DAY_OF_MONTH,5);
}
}
JDK8之后新增的日期、时间类
LocalDate、LocalTime、LocalDateTime
以LocalDate
为例子 其余都大差不差
import javax.security.auth.callback.LanguageCallback;
import java.time.LocalDate;
public class _Local_ {
public static void main(String[] args) {
LocalDate ld = LocalDate.now();//不可变对象
//获取日期对象的信息
int year =ld.getYear();//年
int month=ld.getMonthValue();//月(1-12)
int day =ld.getDayOfMonth();//日
int dayofYear =ld.getDayOfYear();//一年中的第几天
int dayOfWeek=ld.getDayOfWeek().getValue();// 星期几
System.out.println(year+"-"+month+"-"+day);
System.out.println(dayOfWeek);
//修改某个信息 withxxx
LocalDate ld1 = ld.withYear(2049);
LocalDate ld2 = ld.withMonth(12);
//把某个信息加多少 plusxxx
LocalDate ld3 = ld.plusYears(5);
LocalDate ld4 = ld.plusMonths(4);
//把某个信息减多少 minusxxx
LocalDate ld5 = ld.minusDays(5);
LocalDate ld6 = ld.minusYears(1);
//获取指定日期的LocalDate对象
LocalDate ld7 = LocalDate.of(2025,5,19);
//判断两个日期对象 是否相等 是否在前 是否在后
System.out.println(ld5.equals(ld6));
System.out.println(ld5.isAfter(ld6));
System.out.println(ld5.isBefore(ld6));
}
}
LocalDateTime
独有的
转成其他两个对象
LocalDateTime ldt = LocalDateTime,now();
LocalDate ld = ldt.toLocalDate();
LocalTime lt = ldt.toLocalTime();
ZoneId、ZonedDateTime
ZoneId
:时区id
ZonedDateTime
:时区时间
import java.time.Clock;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class _Zone_ {
public static void main(String[] args) {
//获取系统默认时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId.getId());
System.out.println(zoneId);
//获取java支持的所有时区Id
System.out.println(zoneId.getAvailableZoneIds());
//时区id封装成ZoneId
ZoneId zoneId1 = zoneId.of("America/New_York");
//获取某个时区的时间
ZonedDateTime now = ZonedDateTime.now(zoneId1);
System.out.println(now);
//世界标准时间
System.out.println(ZonedDateTime.now(Clock.systemUTC()));
//默认是系统默认时区
System.out.println(ZonedDateTime.now());
//getxxx withxxxx plusxxx minusxxx 都有
}
}
Instant
时间线上的某个时刻/时间戳
精确到纳秒
import java.time.Instant;
public class _Instant_ {
public static void main(String[] args) {
/***
* 作用:
* 做代码的性能分析
* 记录用户的操作时间点
*/
//获取对象
Instant instant = Instant.now();
System.out.println(instant);
//获取总秒数
long second = instant.getEpochSecond();
System.out.println(second);
//不够1秒的纳秒数
int nano = instant.getNano();
System.out.println(nano);
}
}
DateTimeFormatter
格式化器,用于时间的格式化、解析
JDK之前线程不安全
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class _DateTime_ {
public static void main(String[] args) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
//格式化时间
String ts = dateTimeFormatter.format(now);
System.out.println(ts);
//另外的写法
System.out.println(now.format(dateTimeFormatter));
//解析时间
String dateStr = "2033年12月01日 12:12:03";
LocalDateTime ldt = LocalDateTime.parse(dateStr,dateTimeFormatter);
System.out.println(ldt);
}
}
Period、Duration
计算时间间隔
import java.time.LocalDate;
import java.time.Period;
public class _period_ {
public static void main(String[] args) {
LocalDate start = LocalDate.of(2023,12, 1);
LocalDate end = LocalDate.of(2024,1,23);
Period between = Period.between(start, end);
System.out.println(between);
System.out.println(between.getYears());
System.out.println(between.getMonths());
System.out.println(between.getDays());
}
}
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
public class _Duration_ {
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.of(2024,1,10,11,11,20);
LocalDateTime end = LocalDateTime.of(2024,2,1,11,11,11);
Duration between = Duration.between(start, end);
System.out.println(between.toDays());
System.out.println(between.toHours());
System.out.println(between.toSeconds());//秒
System.out.println(between.toMillis());//毫秒
System.out.println(between.toNanos());//纳秒
}
}
Arrays类
操作数组的工具类
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.IntToDoubleFunction;
public class _Arrays_ {
public static void main(String[] args) {
int[] arr = {12,321,5,6,54,112};
System.out.println(Arrays.toString(arr));
//指定范围的拷贝 [beg,end)
int[] arr2 = Arrays.copyOfRange(arr,1,3);
System.out.println(Arrays.toString(arr2));
//拷贝数组 可以指定新数组长度
int[] arr3 = Arrays.copyOf(arr,10);
System.out.println(Arrays.toString(arr3));
//把数组中原数据改为新数据再存进去
//把所有的价格都打八折 放入原数组
double[] prices = {19.2,25.6,123.55,33.6};
Arrays.setAll(prices, new IntToDoubleFunction() {
@Override
public double applyAsDouble(int index) {
return BigDecimal.valueOf(prices[index]).multiply(BigDecimal.valueOf(0.8)).doubleValue();
}
});
for (double price : prices) {
System.out.print(price+" ");
}
System.out.println();
//排序 默认升序 从小到大
Arrays.sort(prices);
for (double price : prices) {
System.out.print(price+" ");
}
System.out.println();
//如果存储的是对象 怎么排序?
/***
* 方法一、类中实现Comparable接口的compareTo方法
* 方法二、使用另外的sort 创建Comparator比较器 创建一个匿名内部类
*/
YStudent[]yStudents = new YStudent[4];
yStudents[0] = new YStudent("悟空",999);
yStudents[1] = new YStudent("白猴子",18);
yStudents[2] = new YStudent("六耳猕猴",347);
yStudents[3] = new YStudent("貂蝉",18);
// Arrays.sort(yStudents);
Arrays.sort(yStudents, new Comparator<YStudent>() {
@Override
public int compare(YStudent o1, YStudent o2) {
return o1.getAge()-o2.getAge();
}
});
for (YStudent yStudent : yStudents) {
System.out.println(yStudent.getName()+"_"+yStudent.getAge());
}
}
}
class YStudent implements Comparable<YStudent> {
private String name;
private int age;
public YStudent() {
}
public YStudent(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 int compareTo(YStudent o) {
/***
* this左边对象 o右边对象
* 正整数 交换
* 负整数 不变位置
*/
return this.age-o.age;
}
}
JDK8新特性
lambda表达式
基本认识
简化匿名内部类的代码写法
public class Test {
public static void main(String[] args) {
Animal dog = new Animal(){
@Override
void run(){
System.out.println("dog~~~");
}
};
dog.run();
//lambda表达式不能简化全部匿名内部类的写法
//只能简化 函数式接口 的匿名内部类
//函数式接口: 1、接口 2、仅有一个抽象方法
Swimming dogSwim = ()->{
System.out.println("🐕🏊🏊🏊🏊");
};
/*
* 等价于
* new Swimming(){
* @Override
* void swim(){
* System.out.println("🐕🏊🏊🏊🏊");
* }
* }
* */
dogSwim.swim();
}
}
abstract class Animal{
abstract void run();
}
@FunctionalInterface
interface Swimming{
String name = "da";
void swim();
}
注意
- 只能简化函数式接口的匿名内部类
- 有且仅有一个抽象方法的接口
省略规则
- 参数类型可以省略不写
- 只有一个参数,在上面的基础上 小括号也可以省略
- 方法体只有一行代码,花括号、分号、return都要去掉
方法引用
进一步简化lambda表达式
标志性符号::
静态方法引用
场景:如果某个lambda表达式仅仅调用一个静态方法,并且前后参数的形式一致 那么可以静态方法引用
/***
* 以下写法都是等价的
*/
// Arrays.sort(yStudents, new Comparator<YStudent>() {
// @Override
// public int compare(YStudent o1, YStudent o2) {
// return o1.getAge()-o2.getAge();
// }
// });
// Arrays.sort(yStudents, (o1, o2) -> o1.getAge()-o2.getAge());
// Arrays.sort(yStudents,((o1, o2) -> CompareByDate.CompareByAge(o1,o2)));
Arrays.sort(yStudents,CompareByDate::CompareByAge);
public class CompareByDate {
public static int CompareByAge(YStudent o1,YStudent o2){
return o1.getAge()-o2.getAge();
}
}
实例方法引用
场景:如果某个lambda表达式仅仅调用一个实例方法,并且前后参数的形式一致 那么可以实例方法引用
/***
* 以下写法都是等价的
*/
// Arrays.sort(yStudents, new Comparator<YStudent>() {
// @Override
// public int compare(YStudent o1, YStudent o2) {
// return o2.getAge()-o1.getAge();
// }
// });
// Arrays.sort(yStudents, (o1, o2) -> o2.getAge()-o1.getAge());
CompareByDate compareByDate = new CompareByDate();
// Arrays.sort(yStudents,((o1, o2) -> compareByDate.compareByAgeDesc(o1,o2)));
Arrays.sort(yStudents,compareByDate::compareByAgeDesc);
package API;
public class CompareByDate {
public int compareByAgeDesc(YStudent o1,YStudent o2){
return o2.getAge()-o1.getAge();
}
}
特定类型的方法引用
场景:如果某个lambda表达式仅仅调用一个实例方法,并且前面参数列表的第一个参数作为方法的主调,后面的所有参数作为该实例方法的参数传入(比如传入 o1 o2 o1.xxx(o2))
,那么可以使用特定类型的方法引用
import java.sql.Array;
import java.util.Arrays;
import java.util.Comparator;
public class Test1 {
public static void main(String[] args) {
String[] names = {"angela","body","cc","Andy","Bob","Alice","Yb0os1"};
//默认是按照ASCII码排序 也即是先大写 后小写
Arrays.sort(names);
for (String name : names) {
System.out.println(name);
}
System.out.println("------------------------");
/***
* 目标:忽略大小写排序
*/
/*Arrays.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);
}
});*/
// Arrays.sort(names, (o1, o2) -> o1.compareToIgnoreCase(o2));
Arrays.sort(names,String::compareToIgnoreCase);
for (String name : names) {
System.out.println(name);
}
}
}
构造器引用
场景:如果某个lambda表达式里只是在创建对象,前后参数情况一致,那么就可以调用构造器引用
public class Test2 {
public static void main(String[] args) {
/*CreatCar bmw = new CreatCar() {
@Override
public Car creat(String name, double price) {
return new Car(name,price);
}
};*/
// CreatCar bmw = (name, price) ->new Car(name, price);
CreatCar cc = Car::new;
cc.creat("BMW",49.6);
System.out.println(cc);
}
}
interface CreatCar{
Car creat(String name,double price);
}
class Car{
private String name;
private double price;
public Car() {
}
public Car(String name, double price) {
this.name = name;
this.price = price;
}
}
Stream流
方便操作集合/数据的一个手段
**注意:**流只能收集一次
简单使用
package _Stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class demo {
public static void main(String[] args) {
List<String>names = new ArrayList<>();
Collections.addAll(names,"张三丰","周芷若","张无忌","赵敏","张三");
System.out.println(names);
//过滤出姓张的
List<String> startZhang = names.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length() == 3).collect(Collectors.toList());
System.out.println(startZhang);
}
}
使用步骤
常用方法
获取Stream流
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Demo1 {
public static void main(String[] args) {
//List Set都是stream
List<String> names = new ArrayList<>();
Collections.addAll(names,"张三丰","周芷若","张无忌","赵敏","张三");
Stream<String> stream = names.stream();
//Map获取Stream 分开处理或者Entry
Map<String,Double>map = new HashMap<>();
map.put("hello",10.0);
Set<Map.Entry<String, Double>> kvs = map.entrySet();
kvs.stream().filter(s->s.getKey().contains("l")).forEach(s-> System.out.println(s.getKey()+" "+s.getValue()));
//数组获取Stream
Integer[] scores = {1,2,3,4,5,6,7,8,9};
Arrays.stream(scores).filter(s->s>5).forEach(s-> System.out.println(s));
Stream.of(scores).filter(s->s<5).forEach(s-> System.out.println(s));
}
}
中间方法
调用完成后返回Steam流对象,所以支持链式编程
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Demo3 {
public static void main(String[] args) {
List<Double>scores = new ArrayList<>();
Collections.addAll(scores,81.5,71.1,90.0,99.5,100.0,21.5,60.5);
//找出成绩大于60小于90分 升序输出 filter sorted
scores.stream().filter(s->s>60&&s<90).sorted().forEach(s-> System.out.println(s));
List<Stu>stus = new ArrayList<>();
stus.add(new Stu("妲己",19));
stus.add(new Stu("牛魔王",51));
stus.add(new Stu("西施",25));
stus.add(new Stu("西施",25));
stus.add(new Stu("貂蝉",21));
stus.add(new Stu("吴",55));
stus.add(new Stu("孙悟空",999));
stus.add(new Stu("王昭君",20));
stus.add(new Stu("猪八戒",888));
stus.add(new Stu("沙和尚",777));
//年龄大于18小于30 降序输出 sorted
stus.stream().filter(s->s.getAge()>18&&s.getAge()<30).sorted((o1,o2)->o2.getAge()-o1.getAge()).forEach(s-> System.out.println(s.getName()+"-"+s.getAge()));
//年龄最大的三个人 limit
stus.stream().sorted((o1,o2)->o2.getAge()-o1.getAge()).limit(3).forEach(s-> System.out.println(s.getName()+"-"+s.getAge()));
//年龄最小的2个人
stus.stream().sorted(Comparator.comparingInt(Stu::getAge)).limit(2).forEach(s-> System.out.println(s.getName()+"-"+s.getAge()));
//年龄大于18 小于30 去除重复名字
//distinct基于equals 和 hashCode比较的
stus.stream().filter(s->s.getAge()>18&&s.getAge()<30).map(Stu::getName).distinct().forEach(System.out::println);
}
}
class Stu{
private String name;
private int age;
public Stu(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;
}
}
终结方法
调用完成后不会返回Stream对象
收集Stream
正则表达式
作用
- 校验数据格式是否合法
- 在一段文本查找满足要求的内容
注意
[]
、与定义字符只能一次匹配一个^
是取反(?i)
是忽略大小写
(?i)abc ABC Abc ABc abc等等都可以匹配
应用
检验电话、邮箱、时间
public class Test1 {
public static void main(String[] args) {
String q1 = "15646816365";
String q2 = "455dada";
System.out.println(checkQQ(q1));
System.out.println(checkQQ(q2));
System.out.println("--------------");
//使用正则表达式
System.out.println("对QQ号码的检查");
System.out.println(checkQQRegex(q1));
System.out.println(checkQQRegex(q2));
System.out.println("对电话|座机号码的检查");
String tel1 = "012-34567891";
String tel2 = "13563075567";
String tel3 = "1006307556a";
System.out.println(checkTel(tel1));
System.out.println(checkTel(tel2));
System.out.println(checkTel(tel3));
System.out.println("对邮箱的检查");
String email1 = "Lenovo@163.com.";
String email2 = "Lenovo@163.com.cn";
String email3 = "L@163.com";
System.out.println(checkEmail(email1));
System.out.println(checkEmail(email2));
System.out.println(checkEmail(email3));
System.out.println("对时间的检查");
String time1 = "0:10:10";
String time2 = "12:60:00";
String time3 = "1:02:2";
System.out.println(checkTime(time1));
System.out.println(checkTime(time2));
System.out.println(checkTime(time3));
}
private static boolean checkQQ(String qq){
/**
* 校验QQ号码是否正确 要求全部是数字 长度是6-20 不能以0开头
*/
int length = qq.length();
if (length<6||length>20||qq==null||qq.startsWith("0"))return false;
for (int i = 0; i < length; i++)
if (qq.charAt(i)<'0'||qq.charAt(i)>'9')return false;
return true;
}
private static boolean checkQQRegex(String qq){
return qq!=null&&qq.matches("[1-9]\\d{5,19}");
}
private static boolean checkTel(String tel){
return tel!=null&&tel.matches("(1[3-9]\\d{9})|(0\\d{2,4}-?[1-9]\\d{4,19})");
}
private static boolean checkEmail(String email){
return email!=null&&email.matches("\\w{2,}@\\w{2,10}(\\.\\w{2,10}){1,2}");
}
private static boolean checkTime(String time){
return time!=null&&time.matches("([0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])");
}
}
查找信息
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test2 {
public static void main(String[] args) {
String data = """
来yb0os1学习java
电话:18666888882,15536588918
邮箱:yb0os1@ityb0os1.com,2536522@OO.com.cn
座机电话:0125-2585461265,0562-46516564
热线电话:400-618-9090,400-618-4000,4006189090,4006184000
""";
//定义爬取规则
String regex = "(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})|\\w{2,}@\\w{2,10}(\\.\\w{2,10}){1,2}|(400-?\\d{3,7}-?\\d{3,7})";
//把正则表达式封装成一个Pattern对象
Pattern p = Pattern.compile(regex);
//通过pattern对象取获取查找内容的匹配器对象
Matcher matcher = p.matcher(data);
//循环爬取信息
while (matcher.find()){//找到一个就返回true
System.out.println(matcher.group());
}
}
}
搜索替换、分割内容
import java.util.Arrays;
public class Test3 {
public static void main(String[] args) {
//需求1:把 古力娜扎6565465dasda迪丽热巴dadsa4156465马儿扎哈231231j卡尔巴哈 的非中文替换为-
String s1 = "古力娜扎6565465dasda迪丽热巴dadsa4156465马儿扎哈231231j卡尔巴哈";
System.out.println(s1.replaceAll("\\w+","-"));
//需求2:我我我我我我喜喜欢JJJJJJJJavvvaaaa! 优化 我喜欢Java!
String s2="我我我我我我喜喜欢JJJJJJJJavvvaaaa!";
/**
* (.) 一组
* \\1 为这个组声明一个组号
* + 必须是重复的
* $1 获取第1组重复的字 只有一个
*/
System.out.println(s2.replaceAll("(.)\\1+","$1"));
//需求3:把 古力娜扎6565465dasda迪丽热巴dadsa4156465马儿扎哈231231j卡尔巴哈 分割为一个数组
String s3="古力娜扎6565465dasda迪丽热巴dadsa4156465马儿扎哈231231j卡尔巴哈";
String[] ss = s3.split("\\w+");
System.out.println(Arrays.toString(ss));
}
}
基本简单练习
买飞机票
public class BugAeroplane {
public static void main(String[] args) {
String type = "头等舱";
int month = 5;double price = 1000;
buy(type, price, month);
}
public static void buy(String tool, double value, int month) {
if (month>=5&&month<=10){
if (tool.equals("头等舱"))
value *= 0.9;
else if (tool.equals("经济舱"))
value *= 0.85;
}else {
if (tool.equals("头等舱"))
value *= 0.7;
else if (tool.equals("经济舱"))
value *= 0.65;
}
System.out.println(month + "月份" + tool + "机票的价格为" + value);
}
}
开发验证码
import java.util.Random;
public class YanZhengMa {
public static void main(String[] args) {
String code = createCode(4);
System.out.println(code);
}
public static String createCode(int n){
Random r = new Random();
String code = "";
for (int i = 0; i < n; i++) {
int type = r.nextInt(3);
switch (type){
case 0:
//数字
code+=r.nextInt(10);
break;
case 1:
//大写字母
code+=(char)(r.nextInt(26)+65);
break;
case 2:
//小写字母
code+=(char)(r.nextInt(26)+97);
break;
}
}
return code;
}
}
评委打分
import java.util.Scanner;
public class GetScore {
public static void main(String[] args) {
System.out.println(getSocre(6));
}
public static double getSocre(int n) {
Scanner sc = new Scanner(System.in);
double finalScore = 0, maxScore = 0, minScore = 100;
for (int i = 0; i < n; i++) {
System.out.println("请您录入第"+(i+1)+"个评委的分数");
double score = sc.nextDouble();
if(score<0||score>100){
System.out.println("不符合");
return -1;
}
finalScore+=score;
maxScore = score>maxScore?score:maxScore;
minScore = score<minScore?score:minScore;
}
finalScore = (finalScore-maxScore-minScore)/(n-2);
return finalScore;
}
}
数字加密
public class Crypt {
public static void main(String[] args) {
System.out.println(encrypt(1983));
System.out.println(decrypt(8346));
}
public static int encrypt(int password){
int result = 0;
while (password>0){
int now = password%10;
result =result*10+(now+5)%10;
password/=10;
}
return result;
}
public static int decrypt(int password){
int result = 0;
while (password>0){
int now = password%10-5;
now = now>0?now:now+10;
result = result*10 + now;
password/=10;
}
return result;
}
}
抢红包
package com.yb0os1.demo;
import java.util.Random;
public class QiangHongBao {
public static void main(String[] args) {
int[] moneys = {9,90,999,1000,5648};
start(moneys);
}
public static void start(int []moneys){
Random r = new Random();
for (int i = 0; i < moneys.length; i++) {
int j = r.nextInt(moneys.length);
int tmp = moneys[i];
moneys[i]= moneys[j];
moneys[j] = tmp;
/*if(i==j)continue;
moneys[i] = moneys[i]+moneys[j];
moneys[j]=moneys[i]-moneys[j];
moneys[i] = moneys[i]-moneys[j];*/
}
System.out.println("红包顺序:");
for (int money : moneys) {
System.out.println(money);
}
}
}
模拟双色球
import java.util.Random;
import java.util.Scanner;
public class DualColouredBall {
public static void main(String[] args) {
int[] numbers = userSelectNumbers();
int[] result = systemSelectNumbers();
print("用户选择",numbers);
print("奖品",result);
isPrice(numbers,result);
}
public static int[] userSelectNumbers() {
int[] numbers = new int[7];
Scanner sc = new Scanner(System.in);
//红球
for (int i = 0; i < numbers.length - 1; i++) {
System.out.println("请输入红球号码(1-33之内且不能重复):");
while (true) {
int number = sc.nextInt();
if (number < 1 || number > 33)
System.out.println("输入不合理,请重新输入");
else if (exist(numbers, number))
System.out.println("重复输入,请重新输入");
else {
numbers[i] = number;
break;
}
}
}
//蓝球
System.out.println("请输入蓝球号码(1-16之内):");
while (true) {
int number = sc.nextInt();
if (number > 16 || number < 1) {
System.out.println("输入不合理,请重新输入");
} else {
numbers[numbers.length - 1] = number;
break;
}
}
return numbers;
}
public static int[] systemSelectNumbers() {
int[] numbers = new int[7];
Random r = new Random();
for (int i = 0; i < numbers.length - 1; i++) {
while (true) {
int number = r.nextInt(33) + 1;
if (!exist(numbers, number)) {
numbers[i] = number;
break;
}
}
}
int number = r.nextInt(16) + 1;
numbers[numbers.length - 1] = number;
return numbers;
}
public static void isPrice(int[] numbers, int[] result) {
int redCount = 0;
int nLen = numbers.length, rLen = result.length;
int blueCount = numbers[nLen - 1] == result[rLen - 1] ? 1 : 0;
for (int i = 0; i < rLen - 1; i++) {
for (int j = 0; j < nLen - 1; j++) {
if (numbers[j]==result[i])
redCount++;
}
}
System.out.println("中"+redCount+"+"+blueCount);
}
public static void print(String name,int[]arr){
System.out.print(name+":");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
if(!(i==arr.length-1)) System.out.print(",");
}
System.out.println();
}
public static boolean exist(int[] numbers, int number) {
for (int n : numbers) {
if (n == number)
return true;
}
return false;
}
}
简单的ATM系统
Test.java
package ATMsystem;
public class Test {
public static void main(String[] args) {
ATM test = new ATM();
test.start();
}
}
Account.java
package ATMsystem;
//账户类
public class Account {
private String id;
private String username;
private char sex;
private double balance;
private String password;
private double limit;
public Account() {
}
public Account(String id, String username, char sex, double balance, String password, double limit) {
this.id = id;
this.username = username;
this.sex = sex;
this.balance = balance;
this.password = password;
this.limit = limit;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getLimit() {
return limit;
}
public void setLimit(double limit) {
this.limit = limit;
}
}
ATM.java
package ATMsystem;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Random;
import java.util.Scanner;
//对账户进行处理
public class ATM {
private ArrayList<Account> accounts = new ArrayList<>();
//开始界面
public void start() {
System.out.println("===欢迎进入yb0os1的银行系统==");
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("1、用户登录");
System.out.println("2、用户开户");
System.out.println("3、退出系统");
System.out.print("请输入:");
String command = sc.next();
switch (command) {
case "1":
login();
break;
case "2":
createAcconut();
break;
case "3":
System.out.println("退出系统成功");
return;
default:
System.out.println("输入有误");
break;
}
}
}
//登录之后的
private void loginAfter(Account ac) {
Scanner sc = new Scanner(System.in);
System.out.println("===欢迎您尊敬的"+ac.getUsername()+"===");
while (true) {
System.out.println("===可以办理以下业务===");
System.out.println("1、查询账户");
System.out.println("2、存款");
System.out.println("3、取款");
System.out.println("4、转账");
System.out.println("5、修改密码");
System.out.println("6、退出");
System.out.println("7、注销账户");
System.out.print("请选择:");
String command = sc.next();
switch (command){
case "1":
viewUser(ac.getId(),ac.getUsername(),ac.getSex(),ac.getBalance(),ac.getLimit());
break;
case "2":
storageMoney(ac);
break;
case "3":
withdrawMoney(ac);
break;
case "4":
Transfer(ac);
break;
case "5":
changePass(ac);
break;
case "6":
return;
case "7":
deleteAccount(ac);
return;
default:
System.out.println("输入有误 请重新输入");
break;
}
}
}
private void deleteAccount(Account ac) {
accounts.remove(ac);
System.out.println("删除成功");
}
private void changePass(Account ac) {
Scanner sc= new Scanner(System.in);
while (true) {
System.out.println("请输入原密码");
String oldPassword = sc.next();
if (!ac.getPassword().equals(oldPassword)){
System.out.println("原密码输入错误,请重新输入");
}
System.out.println("请输入新密码");
String newPassword = sc.next();
if (ac.getPassword().equals(newPassword)){
System.out.println("新密码和原密码相同,请重新输入");
}
ac.setPassword(newPassword);
System.out.println("修改密码成功"+newPassword);
return;
}
}
private void viewUser(String id,String username,char sex,double balance,double limit){
System.out.println("===个人信息===");
System.out.println("用户id:"+id);
System.out.println("用户名:"+username);
System.out.println("性别:"+sex);
System.out.println("余额:"+balance);
System.out.println("每次最大取得金额:"+limit);
System.out.println("==========");
}
private void storageMoney(Account ac){
Scanner sc=new Scanner(System.in);
System.out.println("请输入存放的金额");
double money = sc.nextDouble();
while (money<=0){
System.out.println("输入有误 请重新输入");
money = sc.nextDouble();
}
ac.setBalance(ac.getBalance()+money);
System.out.println(ac.getUsername()+",您现在余额为:"+ac.getBalance()+"元");
}
private void withdrawMoney(Account ac){
Scanner sc=new Scanner(System.in);
System.out.println("请输入取走的金额");
double money = sc.nextDouble();
while (money<=0||money>ac.getBalance()){
System.out.println("输入有误 请重新输入");
money = sc.nextDouble();
}
ac.setBalance(ac.getBalance()-money);
System.out.println(ac.getUsername()+",您取走"+money+"元,"+"现在余额为:"+ac.getBalance()+"元");
}
private void Transfer(Account ac){
if (accounts.size()<2){
System.out.println("账户不足两个,无法进行转账");
return;
}
Scanner sc = new Scanner(System.in);
System.out.println("请输入被转帐人的id");
String id = sc.next();
while (isContain(id)==-1||ac.getId().equals(id)){
System.out.println("输入有误,请重新输入被转账人id");
id = sc.next();
}
int index = isContain(id);
Account ca = accounts.get(index);
System.out.println("请输入转账金额");
double money = sc.nextDouble();
while (money>ac.getBalance()||money<=0){
System.out.println("输入有误,请重新输入转账金额");
money = sc.nextDouble();
}
ac.setBalance(ac.getBalance()-money);
ca.setBalance(ca.getBalance()+money);
System.out.println(ac.getUsername()+"的余额为:"+ac.getBalance());
System.out.println(ca.getUsername()+"的余额为:"+ca.getBalance());
}
//用户登录
private void login(){
if(accounts.isEmpty()){
System.out.println("当前没有账户,请先开户");
return;
}
Scanner sc=new Scanner(System.in);
System.out.println("请输入用户id");
String id = sc.next();
int index = isContain(id);
while (index==-1){
System.out.println("没有该账户,请重新输入");
id = sc.next();
index= isContain(id);
}
System.out.println("请输入密码");
String password = sc.next();
while (!accounts.get(index).getPassword().equals(password)){
System.out.println("密码错误,请重新输入");
password = sc.next();
}
System.out.println("登录成功");
loginAfter(accounts.get(index));
}
//用户创建
private void createAcconut() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名称");
String name = sc.next();
while (name.length() < 5 || name.length() > 20) {
System.out.println("输入的名字过长或者过短 请重新输入");
name = sc.next();
}
System.out.println("请输入用户性别");
char sex = sc.next().toCharArray()[0];
while (!(sex == '男' || sex == '女')) {
System.out.println("性别有误 请重新输入");
sex = sc.next().toCharArray()[0];
}
System.out.println("请输入密码");
String password1 = sc.next();
System.out.println("请确定输入密码");
String password2 = sc.next();
while (!password1.equals(password2)) {
System.out.println("两次输入不一致 请重新输入");
password2 = sc.next();
}
String id = generateId();
while (isContain(id)!=-1){
id = generateId();
}
System.out.println("请输入每次取钱的最大值");
double limit = sc.nextDouble();
while (limit<=0){
System.out.println("输入有误 请重新输入");
limit = sc.nextDouble();
}
accounts.add(new Account(id,name,sex,0,password2,limit));
System.out.println("用户创建成功,您的id为"+id);
}
private String generateId() {
Random r = new Random();
String res = "";
for (int i = 0; i < 8; i++) {
res += (r.nextInt(10));
}
return res;
}
private int isContain(String id){
for (int i =0;i<accounts.size();++i) {
if(accounts.get(i).getId().equals(id)){
return i;
}
}
return -1;
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Demo3 {
public static void main(String[] args) {
List<Double>scores = new ArrayList<>();
Collections.addAll(scores,81.5,71.1,90.0,99.5,100.0,21.5,60.5);
//找出成绩大于60小于90分 升序输出 filter sorted
scores.stream().filter(s->s>60&&s<90).sorted().forEach(s-> System.out.println(s));
List<Stu>stus = new ArrayList<>();
stus.add(new Stu("妲己",19));
stus.add(new Stu("牛魔王",51));
stus.add(new Stu("西施",25));
stus.add(new Stu("西施",25));
stus.add(new Stu("貂蝉",21));
stus.add(new Stu("吴",55));
stus.add(new Stu("孙悟空",999));
stus.add(new Stu("王昭君",20));
stus.add(new Stu("猪八戒",888));
stus.add(new Stu("沙和尚",777));
//年龄大于18小于30 降序输出 sorted
stus.stream().filter(s->s.getAge()>18&&s.getAge()<30).sorted((o1,o2)->o2.getAge()-o1.getAge()).forEach(s-> System.out.println(s.getName()+"-"+s.getAge()));
//年龄最大的三个人 limit
stus.stream().sorted((o1,o2)->o2.getAge()-o1.getAge()).limit(3).forEach(s-> System.out.println(s.getName()+"-"+s.getAge()));
//年龄最小的2个人
stus.stream().sorted(Comparator.comparingInt(Stu::getAge)).limit(2).forEach(s-> System.out.println(s.getName()+"-"+s.getAge()));
//年龄大于18 小于30 去除重复名字
//distinct基于equals 和 hashCode比较的
stus.stream().filter(s->s.getAge()>18&&s.getAge()<30).map(Stu::getName).distinct().forEach(System.out::println);
}
}
class Stu{
private String name;
private int age;
public Stu(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;
}
}