Java基础语法1
Scanner输入
import java.util.Scanner;
public class ScannerDemo1 {
public static void main(String[] args) {
//用户键盘输入名字和年龄,然后打印出来
//1.创建一个扫描器对象,用于接收键盘数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入名字:");
String name = sc.next();//让程序在这一行暂停,等到用户输入一个字符串按了回车键,然后把用户输入的内容赋值给name变量
System.out.println("请输入年龄:");
int age = sc.nextInt(); // nextDouble()读取下一个双精度浮点数
System.out.println("name:" + name + ",age:" + age);
}
}
n位验证码
public class Demo1 {
public static void main(String[] args) {
System.out.println(getVerificationCode(4));
System.out.println(getVerificationCode(6));
}
public static String getVerificationCode(int length){
String code = "";
for(int i = 0; i < length; i++){
int type = (int)(Math.random() * 3);//0,1,2
switch (type){
case 0://数字
int num = (int)(Math.random() * 10);
code += num;
break;
case 1://大写字母
int upper = (int)(Math.random() * 26);
code += (char)(upper + 'A');
break;
case 2://小写字母
int lower = (int)(Math.random() * 26);
code += (char)(lower + 'a');
break;
}
}
return code;
}
}
JavaBean
如果为类创造了有参构造器,那么编译器就不会再创建无参构造器。如果还想使用无参构造器,那么需要自己创建一个无参构造器。
变量存在栈里面,存储对象的地址指向对象,对象存在堆里面,堆里面存储类的地址,指向类,类存在方法区里面,方法区里的方法需要调到栈中执行,执行完之后就清理掉。
Student.java
public class Student { //1.私有成员变量 private String name; private int age; private double chinese; private double math; //提供无参数的构造方法 public Student() {} //提供有参数的构造方法 public Student(String name, int age, double chinese, double math) { this.name = name; this.age = age; this.chinese = chinese; this.math = math; } //提供公开的getter和setter方法 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 double getChinese() { return chinese; } public void setChinese(double chinese) { this.chinese = chinese; } public double getMath() { return math; } public void setMath(double math) { this.math = math; } }
StudentOperator.java
public class StudentOperator { private Student s; public StudentOperator() {} public StudentOperator(Student s) { this.s = s; } public void printScore() { System.out.println("姓名:" + s.getName()); System.out.println("年龄:" + s.getAge()); System.out.println("语文成绩:" + s.getChinese()); System.out.println("数学成绩:" + s.getMath()); } public void printAverageScore() { System.out.println("平均成绩:" + (s.getChinese() + s.getMath())/2.0); } }
Test1.java
public class Test1 { public static void main(String[] args) { Student s1 = new Student("张三", 18, 66, 88); StudentOperator so = new StudentOperator(s1); so.printScore(); } }
CodeBlock
CodeDemo1.java
import java.util.Arrays;
public class CodeDemo1 {
public static String schoolName;
public static String[] cards = new String[10];
//静态代码块:
//格式:static{}
//特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。
//作用:完成类的初始化,例如:对静态变量的初始化赋值。
static{
System.out.println("静态代码块执行了");
schoolName = "黑马程序员";
cards[0] = "A";
cards[1] = "2";
cards[2] = "3";
}
public static void main(String[] args) {
System.out.println("main方法执行了");
System.out.println(schoolName);
System.out.println(Arrays.toString(cards));
}
}
结果
静态代码块执行了 main方法执行了 黑马程序员 [A, 2, 3, null, null, null, null, null, null, null]
CodeDemo2.java
package com_itheima._02CodeBlock;
public class CodeDemo2 {
//实例代码块:无static修饰。属于对象,每次创建对象时,都会优先执行一次。
//作用:初始化对象的实例资源。
{
System.out.println("---------实例代码块---------");
}
public static void main(String[] args) {
System.out.println("---------main方法执行---------");
new CodeDemo2();
new CodeDemo2();
new CodeDemo2();
}
}
结果
---------main方法执行--------- ---------实例代码块--------- ---------实例代码块--------- ---------实例代码块---------
StaticMethod
public class Student {
public static int count = 0;
private String name;
private int age;
private double chinese;
private double math;
public Student() {
count++;
}
public Student(String name, int age, double chinese, double math) {
this.name = name;
this.age = age;
this.chinese = chinese;
this.math = math;
count++;
}
//静态方法中可以访问静态成员变量和静态方法,不能访问非静态成员变量和成员方法
public static int getCount() {
return count;
}
//静态方法中不可以出现this关键字
public static void setCount(int count) {
Student.count = count;
}
//实例方法既可以直接访问静态成员变量和静态方法,也可以访问非静态成员变量和成员方法
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 double getChinese() {
return chinese;
}
public void setChinese(double chinese) {
this.chinese = chinese;
}
public double getMath() {
return math;
}
public void setMath(double math) {
this.math = math;
}
}
ExtendsDemo
子类可以继承父类非私有成员
Extends4Feature 父类、子类与子类方法内相同名字变量的访问
public class Test2 {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
class Fu{
String name = "Fu's name";
}
class Zi extends Fu{
String name = "Zi's name";
public void show(){
String name = "show's name";
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);//父类变量
}
}
结果
show's name Zi's name Fu's name
Extends5Override 重写父类方法
子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public>protected>缺省)
重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
私有方法、静态方法不能被重写,如果重写会报错。
重写的规范:声明不变,重新实现
@Override //方法重写的校验注解:要求方法名称和形参列表与被重写方法一致,否则编译不通过
package com.itheima.extends5Override; public class Test2 { public static void main(String[] args) { Student s = new Student("张三", 18, 66, 88); System.out.println(s); } } class Student{ private String name; private int age; private double chinese; private double math; public Student(){} public Student(String name, int age, double chinese, double math) { this.name = name; this.age = age; this.chinese = chinese; this.math = math; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", chinese=" + chinese + ", math=" + math + '}'; } 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 double getChinese() { return chinese; } public void setChinese(double chinese) { this.chinese = chinese; } public double getMath() { return math; } public void setMath(double math) { this.math = math; } }
结果
Student{name='张三', age=18, chinese=66.0, math=88.0}
Extends6Constructor 构造器
默认情况下,子类全部构造器的第一行代码都是 super()(写不写都有),它会调用父类的无参数构造器。
如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(.),指定去调用父类的有参数构造器,否则会报错。
Test2.java
public class Test2 {
public static void main(String[] args) {
Teacher t = new Teacher("张三",'男',"Java");
System.out.println(t);
}
}
class People{
private String name;
private char sex;
public People(){
System.out.println("People()");
}
public People(String name,char sex){
System.out.println("People(String,char)");
this.name = name;
this.sex = sex;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public char getSex() { return sex; }
public void setSex(char sex) { this.sex = sex; }
}
class Teacher extends People{
private String skill;
public Teacher(){ System.out.println("Teacher()"); }
public Teacher(String name,char sex,String skill){
super(name,sex);//调用父类的构造方法
this.skill = skill;
System.out.println("Teacher(String,char,String)");
}
public String getSkill() { return skill; }
public void setSkill(String skill) { this.skill = skill; }
public String toString(){
return "Teacher{" +
"name=" + getName() +
", sex=" + getSex() +
", skill=" + skill +
"}";
}
}
结果
People(String,char) Teacher(String,char,String) Teacher{name=张三, sex=男, skill=Java}
Test3.java
注意:this(...)调用兄弟构造器或super(...)调用父类构造器,必须放在第一行,而且二者不能同时出现。因为this构造器已经调用了super构造器了
//理解this(...)调用兄弟构造器
public class Test3 {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student("李四", '男', 19);
System.out.println(s1);
System.out.println(s2);
}
}
class Student{
private String name;
private char sex;
private int age;
private String schoolName;
public Student() {
//注意:this(...)调用兄弟构造器或super(...)调用父类构造器,必须放在第一行,而且二者不能同时出现。因为this构造器已经调用了super构造器了
this("张三", '男', 18, "清华大学");
}
public Student(String name, char sex, int age) {
this(name, sex, age, "北京大学");
}
public Student(String name, char sex, int age, String schoolName) {
this.name = name;
this.sex = sex;
this.age = age;
this.schoolName = schoolName;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
", schoolName='" + schoolName + '\'' +
'}';
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public char getSex() { return sex; }
public void setSex(char sex) { this.sex = sex; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getSchoolName() { return schoolName; }
public void setSchoolName(String schoolName) { this.schoolName = schoolName; }
}
结果
Student{name='张三', sex=男, age=18, schoolName='清华大学'}
Student{name='李四', sex=男, age=19, schoolName='北京大学'}
FinalDemo
使用了 static final 修饰的成员变量就被称为常量
作用:常用于记录系统的配置信息。
使用常量记录系统配置信息的优势、执行原理
代码可读性更好,可维护性也更好,
程序编译后,常量会被“宏替换”:出现常量的地方全部会被替换成其记住的字面量,这样可以保证使用常量和直接用字面量的性能是一样的。
Constant.java
public class Constant {
public static final double PI = 3.14;
public static final double E = 2.71828;
public static final double G = 9.8;
public static final double C = 299792458;
public static final String SYSTEM_NAME = "Windows";
}
1.final修饰局部变量:有且仅能被赋值一次
2.final修饰基本类型的变量,变量存储的数据不能被改变。
3.final修饰引用类型的变量,变量存储的地址不能被改变,但地址所指向对象的内容是可以被改变的
finalDemo1.java
public class finalDemo1 {
final int a = 10;
//arr = new int[]{4,5,6};报错
public static void main(String[] args) {
final int[] arr = {1,2,3,4,5,6};
arr[1] = 9;
}
public void test1(){
final int a = 10;
//a = 20;
}
}
//final修饰的类不能被继承
final class A{}
//final修饰的方法不能被重写
class C{
public final void show() { System.out.println("show"); }
}
Enum
枚举都是最终类,不可以被继承,枚举类都是继承java.lang.Enum类的。
枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量会记住枚举类的一个对象。
枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象。
枚举类的第一行:只能罗列枚举对象的名称,这些名称本质是常量
Test.java
public enum A {
//枚举类的第一行:只能罗列枚举对象的名称,这些名称本质是常量
X,Y,Z;
}
public class Test {
public static void main(String[] args) {
A a1 = A.X;
System.out.println(a1);//X
A a2 = A.Y;
System.out.println(a2);//Y
System.out.println(a1.name());// X
System.out.println(a2.name());// Y
System.out.println(a1.ordinal());//0
System.out.println(a2.ordinal());//1
}
}
Test2.java
public class Test2 {
public static void main(String[] args) {
//掌握枚举类的应用场景:做信息的分类和标志
//模拟上下左右移动
//第一种是常量做信息标志和分类,但参数值不受约束
move(Constant.LEFT);
move2(Direction.UP);
}
public static void move2(Direction direction){
switch (direction){
case UP:
System.out.println("向上");break;
case DOWN:
System.out.println("向下");break;
case LEFT:
System.out.println("向左");break;
case RIGHT:
System.out.println("向右");break;
default:
System.out.println("输入有误");
}
}
public static void move(int direction){
switch (direction){
case 0:
System.out.println("向上");break;
case 1:
System.out.println("向下"); break;
case 2:
System.out.println("向左");break;
case 3:
System.out.println("向右");break;
default:
System.out.println("输入有误");
}
}
}
结果
向左
向上
Polymorphsm 多态
多态的前提:有继承/实现关系;存在父类引用子类对象;存在方法重写
使用多态的好处:1.在多态形式下,右边对象是解耦合的,更便于扩展和维护 2.定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。
多态的弊端:在Java多态场景中,当通过父类引用操作子类对象时,无法直接访问子类独有的属性和方法,需要通过向下转型才能调用。
if(a instanceof Dog)可判断对象a是否属于Dog类
public class Test1 {
//多态的前提:有继承/实现关系;存在父类引用子类对象;存在方法重写
//使用多态的好处:1.在多态形式下,右边对象是解耦合的,更便于扩展和维护 2.定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。
//多态的弊端:在Java多态场景中,当通过父类引用操作子类对象时,无法直接访问子类独有的属性和方法,需要通过向下转型才能调用。
//if(a instanceof Dog)可判断对象a是否属于Dog类
public static void main(String[] args) {
Animal a1 = new Dog();
Animal a2 = new Cat();
System.out.println(a1.name);//成员变量:编译看左边,运行看左边 //Animal
System.out.println(a2.name);//Animal
a1.eat();//方法:编译看左边,运行看右边 //Dog eat
a2.eat();//Cat eat
go(a1);
go(a2);
System.out.println("======================");
//强制类型转换的一个注意事项
//存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错,
//运行时,如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常(ClassCastException)的错误出来。
// 比如Dog d2 = (Dog) a2; a2是Cat类型,不能强转为Dog类型
//java 建议强制转换前,应该判断对象的真实类型是否与强转后的类型一致,不一致就报错。
Dog d = (Dog) a1;
d.run();
if(a1 instanceof Dog){
Dog d2 = (Dog) a1;
d2.run();
}
}
public static void go(Animal a){
System.out.println("运行go函数");
a.eat();
//并不知道a1是Dog类型,所以不能直接调用Dog特有方法run
if(a instanceof Dog){
Dog d2 = (Dog) a;
d2.run();
}
}
}
class Animal {
String name = "Animal";
public void eat() { System.out.println("Animal eat"); }
}
class Dog extends Animal {
String name = "Dog";
public void eat() { System.out.println("Dog eat"); }
public void run() { System.out.println("Dog run"); }
}
class Cat extends Animal {
String name = "Cat";
public void eat() { System.out.println("Cat eat"); }
}
结果
Animal Animal Dog eat Cat eat 运行go函数 Dog eat Dog run 运行go函数 Cat eat ====================== Dog run Dog run
PolymorphsmDemo 多态
lombok技术可以实现为类自动添加getter/setter/toString/equals/hashCode等方法
Card.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//lombok技术可以实现为类自动添加getter/setter/toString/equals/hashCode等方法
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Card {
private String carId;
private String name;
private String phone;
private double money;
public void deposit(double money){ this.money += money; }
public void consume(double money){ this.money -= money; }
}
SilverCard.java
public class SilverCard extends Card{
public SilverCard(String carId, String name, String phone, double money) { super(carId, name, phone, money); }
@Override
public void consume(double money) {
System.out.println("您当前消费" + money);
System.out.println("优惠后的消费为" + money * 0.9);
if(getMoney() < money * 0.9){
System.out.println("您的余额不足,请充值");return;
}
setMoney(getMoney() - money * 0.9);
}
}
GoldCard.java
public class GoldCard extends Card{
public GoldCard(String carId, String name, String phone, double money) { super(carId, name, phone, money); }
@Override
public void consume(double money) {
System.out.println("您当前消费" + money);
System.out.println("优惠后的消费为" + money * 0.8);
if(getMoney() < money * 0.8){
System.out.println("您的余额不足,请充值");return;
}
setMoney(getMoney() - money * 0.8);
if(money * 0.8 >= 200){
printTicket();
}
else {
System.out.println("当前消费未满200,您没有优惠券");
}
}
public void printTicket(){ System.out.println("您的优惠券"); }
}
Test.java
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//目标:加油站支付小程序
//1.创建卡片父类,以便创建金卡、银卡对象,封装车主信息
//2.定义卡片父类,里面是金卡和银卡共同的属性和方法
//3.定义金卡类,继承卡片父类,必须重写消费方法,独有功能洗车票
//4.定义银卡类,继承卡片父类,必须重写消费方法
GoldCard gc = new GoldCard("123456789", "张三", "15123456789", 1000);
SilverCard sc2 = new SilverCard("987654321", "李四", "15123456789", 1000);
pay(gc);
}
//支付机:用一个方法来刷卡。可能接收金卡或银卡。根据不同的卡类型,调用不同的消费方法。
public static void pay(Card c) {
System.out.println("请您输入当前消费的金额");
Scanner sc = new Scanner(System.in);
double money = sc.nextDouble();
c.consume(money);
}
}
Abstract Class 抽象类
抽象类中不一定要有抽象方法,有抽象方法的类必须是抽象类
类有的成员:成员变量、方法、构造器,抽象类都可以有,
抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现
一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现。
我们设计这样的抽象类,就是为了更好的支持多态。
A.java
public abstract class A {
private String name;
private int age;
public A() { System.out.println("抽象类A的无参构造器"); }
public A(String name, int age) {
this.name = name;
this.age = age;
System.out.println("抽象类A的有参构造器");
}
public abstract void show();
public void show2(){ System.out.println("抽象类A的show2方法"); }
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; }
}
B.java
public class B extends A{
@Override
public void show() { System.out.println("B类重写show方法"); }
}
AbstractDemo1.java
public class AbstractDemo1 {
public static void main(String[] args) {
B b = new B();
b.setName("zhang san");
b.setAge(20);
b.show();
b.show2();
}
}
res
抽象类A的无参构造器
B类重写show方法
抽象类A的show2方法
模板方法设计模式
people.java
//模板方法设计模式
public abstract class People {
//模板方法是给子类直接使用的,不能被子类重写。
//一旦子类重写了模板方法,模板方法就失效了。
public final void write(){
System.out.println("公共部分1");
writeMain();
System.out.println("公共部分2");
}
public abstract void writeMain();
}
Student.java
public class Student extends People{
@Override
public void writeMain(){ System.out.println("Student writeMain");}
}
Teacher.java
public class Teacher extends People{
@Override
public void writeMain(){ System.out.println("Teacher writeMain"); }
}
Test.java
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.write();//调用父类的write方法
Teacher t = new Teacher();
t.write();//调用父类的write方法
}
}
Interface 接口
JDK 8之前,接口中只能定义常量和抽象方法。
注意:接口不能创建对象。
接口是用来被类实现(implements)的,实现接口的类称为实现类,,一个类可以同时实现多个接口,
1、常量:接口中定义常量可以省略public static final不写,默认会加上去。
2、抽象方法:接口中定义抽象方法的时候可以省略public abstract不写,默认会加上去。
实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则这个类必须定义成抽象类
A.java
package com.itheima.interface1; public interface A { // 1、常量:接口中定义常量可以省略public static final不写,默认会加上去。 //public static final String SCHOOL_NAME = "黑马程序员"; String SCHOOL_NAME = "黑马程序员"; // 2、抽象方法:接口中定义抽象方法的时候可以省略public abstract不写,默认会加上去。 public abstract void run(); void go(); }
B.java
public interface B { void play(); }
Test.java
public class Test {
public static void main(String[] args) {
System.out.println(A.SCHOOL_NAME);
C c = new C();
c.run();
c.go();
c.play();
}
}
//实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则这个类必须定义成抽象类
class C implements A,B{
@Override
public void run() { System.out.println("C类重写接口A中的run方法"); }
@Override
public void go() { System.out.println("C类重写接口A中的go方法"); }
@Override
public void play() { System.out.println("C类重写接口B中的play方法"); }
}
res
黑马程序员
C类重写接口A中的run方法
C类重写接口A中的go方法
C类重写接口B中的play方法
Interface2
//弥补了类单继承的不足,一个类同时可以实现多个接口,使类的角色更多,功能更强大。
//让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现(更利于程序的解耦合
public class Test {
public static void main(String[] args) {
People p = new Student();
Driver d = new Student();d.drive();
BoyFriend bf = new Student();bf.go();
}
}
class Student extends People implements Driver, BoyFriend {
public void drive() { System.out.println("student drive"); }
public void go() { System.out.println("student go"); }
}
interface Driver {
void drive();
}
interface BoyFriend {
void go();
}
class People{}
res
student drive
student go
Interface3Demo
ClassDataInter.java
public interface ClassDataInter {
void printAllStudentInfos();
void printAverageScore();
}
ClassDataInterImpl1.java
// 定义第一套实现类,实现接口:实现打印学生信息,实现打印平均分。
public class ClassDataInterImpl1 implements ClassDataInter{
private Student[] students;
public ClassDataInterImpl1(Student[] students) { this.students = students; }
@Override
public void printAllStudentInfos() {
System.out.println("全班信息如下:");
for (int i = 0; i < students.length; i++) {
System.out.println(students[i].getName() + " " + students[i].getSex() + " " + students[i].getScore());
}
}
@Override
public void printAverageScore() {
double sum = 0;
for (int i = 0; i < students.length; i++) {
sum += students[i].getScore();
}
System.out.println("平均成绩为:" + sum / students.length);
}
}
ClassDataInterImpl2.java
// 定义第二套实现类,实现接口:实现打印学生信息(男女人数),实现打印平均分(去掉最高分和最低分)
public class ClassDataInterImpl2 implements ClassDataInter{
private Student[] students;
public ClassDataInterImpl2(Student[] students) { this.students = students; }
@Override
public void printAllStudentInfos() {
int maleCount = 0;
for (int i = 0; i < students.length; i++) {
Student s = students[i];
System.out.println(s.getName() + " " + s.getSex() + " " + s.getScore());
if(s.getSex() == '男'){ maleCount++; }
}
System.out.println("男学生人数:" + maleCount);
System.out.println("女学生人数:" + (students.length - maleCount));
}
@Override
public void printAverageScore() {
double sum = students[0].getScore();
double max = students[0].getScore();
double min = students[0].getScore();
for (int i = 1; i < students.length; i++) {
sum += students[i].getScore();
max = Math.max(max, students[i].getScore());
min = Math.min(min, students[i].getScore());
}
System.out.println("平均成绩为:" + (sum - max - min) / (students.length - 2));
System.out.println("最高分:" + max);
System.out.println("最低分:" + min);
}
}
Test.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
public class Test {
public static void main(String[] args) {
Student[] allStudents = new Student[10];
allStudents[0] = new Student("张三", '男', 100);
allStudents[1] = new Student("李四", '女', 99);
allStudents[2] = new Student("王五", '男', 98);
allStudents[3] = new Student("赵六", '女', 97);
allStudents[4] = new Student("钱七", '男', 96);
allStudents[5] = new Student("孙八", '女', 95);
allStudents[6] = new Student("周九", '男', 94);
allStudents[7] = new Student("吴十", '女', 93);
allStudents[8] = new Student("郑十一", '男', 92);
allStudents[9] = new Student("冯十二", '女', 91);
//提供两套业务实现方案,支持灵活切换(解耦合)
//定义一个接口(规范思想):必须完成打印全班学生信息,打印平均分。
// 定义第一套实现类,实现接口:实现打印学生信息,实现打印平均分。
// 定义第二套实现类,实现接口:实现打印学生信息(男女人数),实现打印平均分(去掉最高分和最低分)
ClassDataInter cdi1 = new ClassDataInterImpl1(allStudents);
cdi1.printAllStudentInfos();
cdi1.printAverageScore();
System.out.println("------------------------");
ClassDataInter cdi2 = new ClassDataInterImpl2(allStudents);
cdi2.printAllStudentInfos();
cdi2.printAverageScore();
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Student {
private String name;
private char sex;
private double score;
}
res
全班信息如下: 张三 男 100.0 李四 女 99.0 王五 男 98.0 赵六 女 97.0 钱七 男 96.0 孙八 女 95.0 周九 男 94.0 吴十 女 93.0 郑十一 男 92.0 冯十二 女 91.0 平均成绩为:95.5 ------------------------ 张三 男 100.0 李四 女 99.0 王五 男 98.0 赵六 女 97.0 钱七 男 96.0 孙八 女 95.0 周九 男 94.0 吴十 女 93.0 郑十一 男 92.0 冯十二 女 91.0 男学生人数:5 女学生人数:5 平均成绩为:95.5 最高分:100.0 最低分:91.0
Interface4 jdk新特性
A.java
//jdk8之后新特性
public interface A {
// 1、默认方法(普通实例方法):必须加default修饰,
// 默认会用public修饰。如何调用?使用接口的实现类的对象来调用。
default void go(){
System.out.println("interface A:default void go()");
run();
}
//2、私有方法(JDK 9开始才支持的)// 私有的实例方法。
//如何调用?使用接口中的其他实例方法来调用它
private void run(){ System.out.println("interface A:private void run()"); }
// 3、静态方法
// 默认会用public修饰。如何调用?只能使用当前接口名来调用。
public static void show(){ System.out.println("interface A:public static void show()"); }
}
Test.java
public class Test {
public static void main(String[] args) {
AImpl a = new AImpl();
a.go();
A.show();
}
}
class AImpl implements A { }
res
interface A:default void go() interface A:private void run() interface A:public static void show()
interface5
1、接口与接口可以多继承:一个接口可以同时继承多个接口[重点]。
2、类与类:单继承 一个类只能继承一个直接父类。
3、类与接口:多实现,一个类可以同时实现多个接口。
4、接口与接口: 多继承,一个接口可以同时继承多个接口。
5、一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承,也不支持多实现。[了解]
6、一个类继承了父类,又同时实现了接口,如果父类中和接口中有同名的方法,实现类会优先用父类的。
7、一个类实现了多个接口,如果多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
public class Test {
public static void main(String[] args) {
Dog d = new Dog();
d.show();
d.go();
}
}
// 1、接口与接口可以多继承:一个接口可以同时继承多个接口[重点]。
// 类与类:单继承 一个类只能继承一个直接父类
// 类与接口:多实现,一个类可以同时实现多个接口。
// 接口与接口: 多继承,一个接口可以同时继承多个接口。
interface A {
void show1();
}
interface B {
void show2();
}
interface C extends A, B {
void show3();
}
class D implements C {
public void show1() { System.out.println("show1"); }
public void show2() { System.out.println("show2"); }
public void show3() { System.out.println("show3"); }
}
//2、一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承,也不支持多实现。[了解]
interface A1 {
void show();
}
interface B1 {
String show();
}
/*
class C1 implements A1, B1 {
//报错
public void show() {
System.out.println("show");
}
public String show() {
return "show";
}
}*/
//3.一个类继承了父类,又同时实现了接口,如果父类中和接口中有同名的方法,实现类会优先用父类的。
interface A2 {
default void show() { System.out.println("interface A2:default void show()"); }
}
class Animal{
public void show() { System.out.println("Animal:public void show()"); }
}
class Dog extends Animal implements A2 {
public void go(){
show();//Animal:public void show()
super.show();//Animal:public void show()
A2.super.show();//interface A2:default void show()
}
}
//4. 一个类实现了多个接口,如果多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
res
Animal:public void show() Animal:public void show() Animal:public void show() interface A2:default void show()
InterfaceDemo 家电控制模拟
Switch.java
public interface Switch {
void press();
}
JD.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JD implements Switch{
private String name;
private boolean status;//默认值为false
@Override
public void press() {
//控制当前设备开关
status = !status;
}
}
TV.java
public class TV extends JD{ public TV(String name, boolean status) { super(name, status); } }
WashMachine.java
public class WashMachine extends JD{ public WashMachine(String name, boolean status) { super(name, status); } }
Lamp.java
public class Lamp extends JD{ public Lamp(String name, boolean status) { super(name, status); } }
Air.java
public class Air extends JD{ public Air(String name, boolean status) { super(name, status); } }
SmartControl.java
public class SmartControl {
private static final SmartControl sm = new SmartControl();
private SmartControl() {}
public static SmartControl getInstance() { return sm; }
public static void printAllstatus(JD[] jds) {
for (int i = 0; i < jds.length; i++) {
System.out.println((i+1) + " " + jds[i].getName() + "目前状态:" + (jds[i].isStatus() ? "开" : "关"));
}
}
public void control(JD jd){
System.out.println(jd.getName() + "目前状态:" + (jd.isStatus() ? "开" : "关"));
System.out.println("开始您的操作");
jd.press();
System.out.println(jd.getName() + "状态变成:" + (jd.isStatus() ? "开" : "关"));
}
}
Test.java
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// 目标:面向对象编程实现智能家居控制系统。
// 角色:设备(吊灯,电视机,洗衣机,落地窗,....)/1具备的功能:开和关。
//谁控制他们:智能控制系统(单例对象),控制调用设备的开和关。
//1、定义设备类:创建设备对象代表家里的设备。
//2、准备这些设备对象,放到数组中,代表整个家庭的设备。
JD[] jds = new JD[4];
jds[0] = new TV("电视", false);
jds[1] = new WashMachine("洗衣机", false);
jds[2] = new Lamp("吊灯", false);
jds[3] = new Air("空调", false);
//3、为每个设备制定一个开个关的功能。定义一个接口,让JD实现开关功能。
//4、创建智能控制系统对象,控制设备开和关。
//5、控制电视
SmartControl smartControl = SmartControl.getInstance();
//smartControl.control(jds[0]);
//6 、提示用户操作,a、展示全部设备的当前情况。b、让用户选择哪一个操作// 打印全部设备的开和关的现状。
while(true){
SmartControl.printAllstatus(jds);
System.out.println("请选择您要操作的设备序号,输入q退出");
Scanner sc = new Scanner(System.in);
String command = sc.next();
switch (command){
case "1":
smartControl.control(jds[0]);break;
case "2":
smartControl.control(jds[1]);break;
case "3":
smartControl.control(jds[2]);break;
case "4":
smartControl.control(jds[3]);break;
case "q":
System.out.println("感谢使用智能控制系统,欢迎下次使用");return;
default:
System.out.println("您输入的序号有误,请重新输入");
}
}
}
}
抽象类与接口的区别
相同点:
1、多是抽象形式,都可以有抽象方法,都不能创建对象。
2、都是派生子类形式:抽象类是被子类继承使用,接口是被实现类实现。
3、一个类继承抽象类,或者实现接口,都必须重写完他们的抽象方法,否则自己要成为抽象类或者报错!
4、都能支持的多态,都能够实现解耦合。
不同点:
1、抽象类中可以定义类的全部普通成员,接口只能定义常量,抽象方法(JDK8新增的三种方式)
2、抽象类只能被类单继承,接口可以被类多实现。
3、一个类继承抽象类就不能再继承其他类,一个类实现了接口(还可以继承其他类或者实现其他接口)。
4、抽象类体现模板思想:更利于做父类,实现代码的复用性。最佳实践
5、接口更适合做功能的解耦合:解耦合性更强更灵活。最佳实践
SingleInstance 单例设计模式
A.java
//饿汉式单例设计模式:
public class A {
//2.定义一个静态变量,用于基本本类的唯一实例
private static A a = new A();
//1. 私有化构造方法
private A(){}
public static A getInstance(){ return a; }
}
B.java
//懒汉式单例设计模式:要用类的对象时,才创建对象,第一次用到时创建,以后都用同一个对象。
public class B {
private static B instance;
private B() { }
public static B getInstance() {
if (instance == null) {
instance = new B();
}
return instance;
}
}
Test.java
public class Test {
public static void main(String[] args) {
//目标:设计单例类
//A a1 = new A(); //错误,不能new对象
A a1 = A.getInstance();
A a2 = A.getInstance();
System.out.println(a1 == a2);//true
}
}
InnerClass 内部类
Outer.java
public class Outer {
public static String schoolName = "黑马程序员";
private int age;
public Outer() { System.out.println("Outer()"); }
public void run(){ System.out.println("Outer.run()"); }
//成员内部类:无static修饰,属于外部类的对象持有的。
public class Inner {
private String name;
public Inner() { System.out.println("Inner()"); }
public Inner(String name) {
System.out.println("Inner(String name)");
this.name = name;
}
public void show() {
System.out.println("Inner show");
//成员内部类中可以直接访问外部类的静态成员
System.out.println("Outer:public static String schoolName:" + Outer.this.schoolName);
System.out.println("Outer:private int age:" + Outer.this.age);
Outer.this.run();//访问外部类的成员方法
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
}
InnerClassDemo1.java
public class InnerClassDemo1 {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.setName("张三");
oi.show();
//成员内部类中可以直接访问外部类的静态成员,也可以直接访问外部类的实例成员
}
}
InnerClass2
Outer.java
public class Outer {
public static String schoolName = "黑马程序员";
private String name;
public static class Inner {
public void show() {
System.out.println("public static class Inner.show");
System.out.println("Outer.schoolName:" + Outer.schoolName);//静态内部类中可以直接访问外部类的静态成员
//System.out.println("Outer.name:" + Outer.this.name);//静态内部类中不可以直接访问外部类的实例成员
}
}
public static String getSchoolName() { return schoolName; }
public static void setSchoolName(String schoolName) { Outer.schoolName = schoolName; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
InnerClassDemo2.java
public class InnerClassDemo2 {
public static void main(String[] args) {
//目标:搞清楚静态内部类的语法
// 创建对象:外部类名.内部类名对象名=new 外部类名.内部类名();
//静态内部类中是否可以直接访问外部类的静态成员?可以!
//静态内部类中是否可以直接访问外部类的实例成员?不可以!
Outer.Inner oi = new Outer.Inner();
}
}
InnerClass AnonymousClass
Test.java
public class Test { public static void main(String[] args) { //认识匿名内部类 //匿名内部类本质是一个子类,同时会立即构建一个子类对象 Animal a = new Animal() { @Override public void cry() { System.out.println("cat cry"); } }; a.cry(); } } abstract class Animal { public abstract void cry(); }
res
cat cry
Test2.java
public class Test2 { public static void main(String[] args) { //目标:搞清楚匿名内部类的使用形式(语法): 通常可以做为一个对象参数传输给方法使用。 //需求:学生,老师都要参加游泳比赛。 Swim s1 = new Swim() { @Override public void swimming() { System.out.println("匿名内部类实现Swim接口,创建对象s1"); } }; start(s1); System.out.println("--------------------"); start(new Swim() { @Override public void swimming() { System.out.println("匿名内部类实现Swim接口,创建对象s2"); } }); } public static void start(Swim s){ System.out.println("开始。。"); s.swimming(); System.out.println("结束。。"); } } interface Swim { void swimming(); }
res
开始。。 匿名内部类实现Swim接口,创建对象s1 结束。。 -------------------- 开始。。 匿名内部类实现Swim接口,创建对象s2 结束。。
Test3.java
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test3 {
public static void main(String[] args) {
// 目标:搞清楚几个名内部类的使用场景。
// 需求:创建一个登录窗口,窗口上只有一个登录按钮
JFrame win = new JFrame("登录窗口");
win.setSize(300,200);
win.setLocationRelativeTo(null);//居中显示。
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
win.add(panel); // 添加面板
JButton btn = new JButton("登录");
panel.add(btn);
//java要求必须给这个按钮添加一个点击事件监听器对象,这样就可以监听用户的点击操作,就可以做出反应。
//开发中不是我们要主动去写匿名内部类,而是用别人的功能的时候,别人可以让我们写一个匿名内部类吗,我们才会写!
/*
ClickListener cl = new ClickListener();
btn.addActionListener(cl);*/
//更简便的写法是使用匿名内部类,匿名内部类对象是在创建的时候,就直接调用了addActionListener方法,把匿名内部类对象传递给addActionListener方法。
btn.addActionListener(new ActionListener() {
private int count = 0;
@Override
public void actionPerformed(ActionEvent e) { System.out.println("用户第" + ++count + "次点击登陆按钮"); }
});
win.setVisible(true);
}
}
class ClickListener implements ActionListener {
private static int count = 0;
@Override
public void actionPerformed(ActionEvent e) { System.out.println("用户第" + ++count + "次点击登陆按钮"); }
}
res
用户第1次点击登陆按钮
用户第2次点击登陆按钮
用户第3次点击登陆按钮
用户第4次点击登陆按钮
Test4.java Arrays.sort
import java.util.Arrays;
import java.util.Comparator;
public class Test4 {
public static void main(String[] args) {
Student[] students = new Student[6];
students[0] = new Student("张三", 35, 170, '男');
students[1] = new Student("李四", 28, 168, '男');
students[2] = new Student("王五", 25, 165, '女');
students[3] = new Student("赵六", 19, 172, '男');
students[4] = new Student("孙七", 27, 170, '女');
students[5] = new Student("钱八", 36, 168, '女');
//需求:按钮年龄升序排序。可以调用sun公司写好的API直接对数组进行排序。
// public static void sort(T[]a,Comparator<T> c)
// 参数一:需要排序的数组
// 参数二:需要给sort声明一个Comparator比较器对象(指定排序的规则)
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//指定排序规则:
//如果你认为左边对象要放后面,那么返回正整数。
//如果你认为左边对象要放前面,那么返回负整数。
//如果两边相等那么返回0。
return o1.getAge() - o2.getAge();
}
});
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]);
}
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Student{
private String name;
private int age;
private double height;
private char sex;
}
res
Student(name=赵六, age=19, height=172.0, sex=男) Student(name=王五, age=25, height=165.0, sex=女) Student(name=孙七, age=27, height=170.0, sex=女) Student(name=李四, age=28, height=168.0, sex=男) Student(name=张三, age=35, height=170.0, sex=男) Student(name=钱八, age=36, height=168.0, sex=女)
Lambda
Lambda表达式:JDK8 开始新增的一种语法形式,它表示函数。
可以用于替代某些匿名内部类对象,从而让程序更简洁,可读性更好
(被重写方法的形参列表)->{被重写方法的方法体代码}
Lambda并不是可以简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类。
函数式接口:只有一个抽象方法的接口。声明函数式接口的注解:@FunctionalInterface
LambdaDemo1.java
public class LambdaDemo1 {
public static void main(String[] args) {
Animal a = new Animal() {
@Override
public void cry() {
System.out.println("叫了一声");
}
};
a.cry();
//错误示范:Lambda并不是可以简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类。
/*Animal a1 = () -> {
@Override
public void cry() {
System.out.println("叫了一声");
}
};*/
Swim s1 = () -> {
System.out.println("s1调用swimming方法");
};
s1.swimming();
}
}
//函数式接口:只有一个抽象方法的接口。
@FunctionalInterface //声明函数式接口的注解
interface Swim{
void swimming();
}
abstract class Animal {
public abstract void cry();
}
res
叫了一声
s1调用swimming方法
LambdaDemo2.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Comparator;
public class LambdaDemo2 {
public static void main(String[] args) {
test1();
test2();
}
public static void test1(){
Student[] students = new Student[6];
students[0] = new Student("张三", 35, 170, '男');
students[1] = new Student("李四", 28, 168, '男');
students[2] = new Student("王五", 25, 165, '女');
students[3] = new Student("赵六", 19, 172, '男');
students[4] = new Student("孙七", 27, 170, '女');
students[5] = new Student("钱八", 36, 168, '女');
//需求:按钮年龄升序排序。可以调用sun公司写好的API直接对数组进行排序。
// public static void sort(T[]a,Comparator<T> c)
// 参数一:需要排序的数组
// 参数二:需要给sort声明一个Comparator比较器对象(指定排序的规则)
/*Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//指定排序规则:
//如果你认为左边对象要放后面,那么返回正整数。
//如果你认为左边对象要放前面,那么返回负整数。
//如果两边相等那么返回0。
return o1.getAge() - o2.getAge();
}
});*/
/*Arrays.sort(students, (o1, o2) -> {
return o1.getAge() - o2.getAge();
});*/
Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]);
}
}
public static void test2(){
// 目标:搞清楚几个名内部类的使用场景。
// 需求:创建一个登录窗口,窗口上只有一个登录按钮
JFrame win = new JFrame("登录窗口");
win.setSize(300,200);
win.setLocationRelativeTo(null);//居中显示。
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
win.add(panel); // 添加面板
JButton btn = new JButton("登录");
panel.add(btn);
//java要求必须给这个按钮添加一个点击事件监听器对象,这样就可以监听用户的点击操作,就可以做出反应。
//开发中不是我们要主动去写匿名内部类,而是用别人的功能的时候,别人可以让我们写一个匿名内部类吗,我们才会写!
/*btn.addActionListener((ActionEvent e) -> {
System.out.println("点击登陆按钮");
});*/
/*btn.addActionListener((e) -> {
System.out.println("点击登陆按钮");
});*/
btn.addActionListener(e -> System.out.println("点击登陆按钮"));
win.setVisible(true);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Student{
private String name;
private int age;
private double height;
private char sex;
}
res
Student(name=赵六, age=19, height=172.0, sex=男) Student(name=王五, age=25, height=165.0, sex=女) Student(name=孙七, age=27, height=170.0, sex=女) Student(name=李四, age=28, height=168.0, sex=男) Student(name=张三, age=35, height=170.0, sex=男) Student(name=钱八, age=36, height=168.0, sex=女) 点击登陆按钮 点击登陆按钮
Method1Reference LambdaSort
Demo2.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
public class Demo2 {
public static void main(String[] args) {
Student2[] students = new Student2[6];
students[0] = new Student2("张三", 35, 170, '男');
students[1] = new Student2("李四", 28, 168, '男');
students[2] = new Student2("王五", 25, 165, '女');
students[3] = new Student2("赵六", 19, 172, '男');
students[4] = new Student2("孙七", 27, 170, '女');
students[5] = new Student2("钱八", 36, 168, '女');
//Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());
//Arrays.sort(students, (o1, o2) -> Student.compareByAge(o1, o2));
//如果某个Lambda表达式里只是调用一个静态方法,并且“→”前后参数的形式一致,就可以使用静态方法引用。
//Arrays.sort(students, Student2::compareByAge);
Arrays.sort(students, Student2::compareByAge);
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]);
}
System.out.println("=======================================================");
Student2 t = new Student2();//创建对象来调用静态方法
Arrays.sort(students, t::compareByHeight);
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]);
}
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Student2{
private String name;
private int age;
private double height;
private char sex;
public static int compareByAge(Student2 o1, Student2 o2){ return o1.getAge() - o2.getAge(); }
//Arrays.sort 使用的比较器需要遵循 Comparator<T> 接口规范,其 compare 方法必须返回 int 类型(表示大小关系:负数、零、正数)。
// 如果改为 double,会导致编译错误,因为方法签名不匹配。
public int compareByHeight(Student2 o1, Student2 o2){
return Double.compare(o1.getHeight(), o2.getHeight()); // 使用Double.compare避免精度问题
}
}
res
Student2(name=赵六, age=19, height=172.0, sex=男) Student2(name=王五, age=25, height=165.0, sex=女) Student2(name=孙七, age=27, height=170.0, sex=女) Student2(name=李四, age=28, height=168.0, sex=男) Student2(name=张三, age=35, height=170.0, sex=男) Student2(name=钱八, age=36, height=168.0, sex=女) ======================================================= Student2(name=王五, age=25, height=165.0, sex=女) Student2(name=李四, age=28, height=168.0, sex=男) Student2(name=钱八, age=36, height=168.0, sex=女) Student2(name=孙七, age=27, height=170.0, sex=女) Student2(name=张三, age=35, height=170.0, sex=男) Student2(name=赵六, age=19, height=172.0, sex=男)
Demo3.java
java已经为我们提供了字符串按照首字母忽略大小写比较的方法:compareToIgnoreCase。
o1.compareToIgnoreCase(o2) 相当于 o1-o2
import java.util.Arrays;
import java.util.Comparator;
public class Demo3 {
public static void main(String[] args) {
// 目标:特定类型的方法引用。
// 需求:有一个字符串数组,里面有一些人的名字都是,英文名称,请按照名字的首字母升序排序。
String[] names = {"caocao","Alice", "Bob","apple", "Charlie", "David", "Eve", "Fred", "Ginny", "Harriet", "Irene", "Joseph"};
System.out.println("a".compareToIgnoreCase("b"));//-1
System.out.println("b".compareToIgnoreCase("a"));//1
System.out.println("b".compareToIgnoreCase("B"));//0
//把这个数组进行排序:Arrays.sort(names,Comparator)
// Arrays.sort(names)://默认就是按照首字母的编号升序排序。
// 要求:忽略首字母的大小进行升序排序(java官方默认是搞不定的,需要我们自己指定比较规则)
/*
Arrays.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);//java已经为我们提供了字符串按照首字母忽略大小写比较的方法:compareToIgnoreCase
}
});*/
//如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,
//后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。
//Arrays.sort(names,(String o1, String o2) -> o1.compareToIgnoreCase(o2));
Arrays.sort(names,(o1, o2) -> o1.compareToIgnoreCase(o2));
//特定类型方法引用:类型名称::方法名
Arrays.sort(names,String::compareToIgnoreCase);
System.out.println(Arrays.toString(names));
}
}
res
-1
1
0
[Alice, apple, Bob, caocao, Charlie, David, Eve, Fred, Ginny, Harriet, Irene, Joseph]
Demo4.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
public class Demo4 {
public static void main(String[] args) {
//理解构造器引用
/*
CarFactory cf = new CarFactory() {
@Override
public Car getCar(String name) {
return new Car(name);
}
};*/
//CarFactory cf = name -> new Car(name);
//如果某个Lambda表达式里只是在创建对象,并且“→”前后参数情况一致,就可以使用构造器引用。
CarFactory cf = Car::new;
Car c1 = cf.getCar("保时捷");
System.out.println(c1);
}
}
interface CarFactory {
Car getCar(String name);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Car {
private String name;
}
res
Car(name=保时捷)
String
StringDemo1.java
import java.util.Scanner;
public class StringDemo1 {
public static void main(String[] args) {
//只要是以"..."方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份;
//通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中
// 2、方式二:通过构造器初始化对象。
String s2 = new String();// 不推荐
System.out.println(s2);//““空字符串
String s3 = new String("hello,黑马");// 不推荐
System.out.println(s3);
char[] chars = {'h','e','l','l','o'};
String s4 = new String(chars);
System.out.println(s4);
byte[] bytes = {97,98,99,65,66,67};
String s5 = new String(bytes);
System.out.println(s5);
System.out.println("----------");
//只有""给出的字符串对象放在字符串常量池,相同内容只放一个。
String t1 = "abc";
String t2 = "abc";
System.out.println(t1 == t2);//true
String t3 = new String("abc");
String t4 = new String("abc");
//通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中
System.out.println(t3 == t4);//false
System.out.println("----------------------------------------");
//调用字符串的方法,处理字符串数据。
//简易版的登录
String okLoginName = "admin";
System.out.println("请输入用户名:");
Scanner sc = new Scanner(System.in);
String loginName = sc.next();
//千万要注意:equals方法比较的是内容,==比较的是地址。
//判断字符串内容,建议用String提供的equals方法,只关心内容一样,就返回true,不关心地址。
if(loginName.equals(okLoginName)){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
System.out.println("----------------------------------------");
System.out.println("请您输入手机号");
String phone = sc.next();
System.out.println("系统显示以下手机号码进入");
//截取手机号中间四位,显示为****
String newPhone = phone.substring(0,3) + "****" + phone.substring(7);//public string substring(int beginIndex,int endIndex)
}
}
StringDemo2_Vertification.java
public class StringDemo2_VerificationCode {
public static void main(String[] args) {
System.out.println(getVerificationCode(4));
System.out.println(getVerificationCode(6));
System.out.println(getVerificationCode(8));
}
public static String getVerificationCode(int length) {
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
String code = "";
for (int i = 0; i < length; i++) {
int index = (int) (Math.random() * str.length());
code += str.charAt(index);
}
return code;
}
}
ArrayList
ArrayListDemo1.java
import java.util.ArrayList;
public class ArrayListDemo1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");list.add("李四");list.add("王五");list.add("赵六");
list.add("田七");list.add("老八");list.add("孙九");list.add("钱十");
System.out.println(list);
System.out.println(list.get(2));//获取索引为2的元素
//删除索引为4的元素
list.remove(4);
list.remove("田七");
System.out.println(list);
//修改索引为2的元素
list.set(2, "李华");
}
}
res
[张三, 李四, 王五, 赵六, 田七, 老八, 孙九, 钱十]
王五
[张三, 李四, 王五, 赵六, 老八, 孙九, 钱十]
GUI
JFrameDemo1.java
import javax.swing.*;
public class JFrameDemo1 {
public static void main(String[] args) {
//目标:快速入门GUI Swing编程
//1.创建一个窗口,有一个登陆按钮
JFrame jf = new JFrame("登录窗口");
jf.setSize(400,300);
jf.setLocationRelativeTo(null);//居中显示。
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗口关闭的时候,程序也关闭。
JPanel panel = new JPanel();
jf.add(panel);
JButton jb = new JButton("登录");
jb.setBounds(100,100,100,50);//设置按钮的大小和位置。
panel.add(jb);
jf.setVisible(true);//显示窗口。
}
}
Test.java
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Test {
public static void main(String[] args) {
//1.创建一个窗口,有一个登陆按钮
JFrame jf = new JFrame("登录窗口");
jf.setSize(400,300);
jf.setLocationRelativeTo(null);//居中显示。
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗口关闭的时候,程序也关闭。
JPanel panel = new JPanel();
jf.add(panel);
JButton jb = new JButton("登录");
jb.setBounds(100,100,100,50);//设置按钮的大小和位置。
panel.add(jb);
//给按钮添加点击事件监听器。
//e是事件对象,里面封装了事件发生时的一些信息。
jb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(jf,"点击了按钮");
jf.requestFocus(); // 重新让窗口获取焦点
}
});
//需求:监听用户键盘上下左右四个按键的事件。
//给jf窗口整体绑定按键事件
jf.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//获取键盘按下的键值
int keyCode = e.getKeyCode();//拿事件源头的键帽编号
if(keyCode == KeyEvent.VK_UP){
System.out.println("用户按下了上键");
}else if(keyCode == KeyEvent.VK_DOWN){
System.out.println("用户按下了下键");
}else if(keyCode == KeyEvent.VK_LEFT){
System.out.println("用户按下了左键");
}else if(keyCode == KeyEvent.VK_RIGHT){
System.out.println("用户按下了右键");
}
}
});
jf.requestFocus();//让窗口成为焦点,才可以监听键盘事件。
jf.setVisible(true);//显示窗口。
}
}