当前位置: 首页 > news >正文

java学习笔记7——面向对象

关键字:static

类变量

静态变量的内存解析:

相关代码:

public class ChineseTest {public static void main(String[] args) {System.out.println(Chinese.nation); //null 没赋值前System.out.println(Chinese.nation); //中国 静态变量赋值之后Chinese c1 = new Chinese();c1.name = "姚明";c1.age = 40;c1.nation = "China";Chinese c2 = new Chinese();c2.name = "刘翔";c2.age = 39;System.out.println(c1);System.out.println(c2);System.out.println(c1.nation); // ChinaSystem.out.println(c2.nation); // Chinac2.nation = "CHN";System.out.println(c1.nation); // CHNSystem.out.println(c2.nation); // CHN}
}
class Chinese { //中国人类//非静态变量、实例变量String name;int age;//静态变量、类变量/*** China* China* CHN* CHN*/static String nation = "中国";/*** China* null* China* CHN*/
//    String nation;@Overridepublic String toString() {return "Chinese{" +"name='" + name + '\'' +", age=" + age +'}';}
}

类方法(class method)

案例1:

编写一个类实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额"、“利率"、“最小余额",
定义封装这些属性的方法,账号要自动生成。编写主类,使用银行账户类,输入、输出3个储户的上述信息。考虑:哪些属性可以设计成static属性x

相关代码:

AccountTest 
public class AccountTest {public static void main(String[] args) {Account acct1 = new Account();System.out.println(acct1);Account acct2 = new Account("123456", 2000);System.out.println(acct2);Account.setInterestRate(0.0123);Account.setMinBalance(10);System.out.println("银行存款的利率为:" + Account.getInterestRate());System.out.println("银行存款的额度为:" + Account.getMinBalance());}
}
Account 
public class Account {private int id; //账号private String password; //密码private double balance; //余额private static double interestRate; //利率private static double minBalance = 1.0; //最小余额private static int init = 1001; //用于自动生成id的基数public Account(){this.id = init;init++;password = "000000";}public Account(String password, double balance) {this.password = password;this.balance = balance;this.id = init;init++;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}public static double getInterestRate() {return interestRate;}public static void setInterestRate(double interestRate) {Account.interestRate = interestRate;}public static double getMinBalance() {return minBalance;}public static void setMinBalance(double minBalance) {Account.minBalance = minBalance;}@Overridepublic String toString() {return "Account{" +"id=" + id +", password='" + password + '\'' +", balance=" + balance +'}';}
}

面试题:

public class StaticTest {public static void main(String[] args) {Order order = null;//可以打印出来,静态并不依赖于对象,直接通过类调用即可order.hello(); //hello!System.out.println(order.count); //1}
}
class Order{public static int count = 1;public static void hello() {System.out.println("hello!");}
}

本章总结:

static关键字的使用1. static:静态的2.static 用来修饰的结构:属性、方法;代码块、内部类3.static修饰属性3.1 复习:变量的分类方式1:按照数据类型:基本数据类型、引用数据类型方式2:按照类中声明的位置成员变量:按照是否使用static修饰进行分类:使用static修饰的成员变量:静态变量、类变量不使用static修饰的成员变量:非静态变量、实例变量局部变量:方法内、方法形参、构造器内、构造器形参、代码块内等。3.2 静态变量:类中的属性使用static进行修饰。对比静态变量与实例变量:① 个数> 静态变量: 内存空间中只有一份,被类的多个对象所共享。> 实例变量: 类的每一个实例(或对象)都保存着一份实例变量。② 内存位置> 静态变量: jdk6及之前:存放在方法区。jdk7之后:存放在堆空间> 实例变量: 存放在堆空间的对象实体中③ 加载时机> 静态变量: 随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份。> 实例变量: 随着对象的创建而加载。每个对象拥有一份实例变量。④ 调用者> 静态变量: 可以被类直接调用,也可以使用对象调用。> 实例变量: 只能使用对象进行调用。⑤ 判断是否可以调用 ---> 从生命周期的角度解释类变量             实例变量类             yes                no对象           yes                yes⑥ 消亡时机> 静态变量: 随着类的卸载而消亡> 实例变量: 随着对象的消亡而消亡4.static修饰方法:(类方法、静态方法)> 随着类的加载而加载
> 可以通过"类.静态方法"的方式,直接调用静态方法
> 静态方法内可以调用静态的属性或静态的方法(属性和方法的前缀使用的是当前类,可以省略)不可以调用非静态的结构。(比如:属性、方法)类变量             实例变量类             yes                no对象           yes                yes
> static修饰的方法内,不能使用this和super> 补充:在类的非静态方法中,可以调用当前类中的静态结构(属性、方法)或非静态结构(属性、方法)5.开发中,什么时候需要将属性声明为静态的?> 判断当前类的多个实例是否能共享此成员变量,且此成员变量的值是相同的。> 开发中,常将一些常量声明是静态的。比如:Math类中的PI什么时候需要将方法声明为静态的?> 方法内操作的变量如果都是静态变量(而非实例变量)的话,则此方法建议声明为静态方法> 开发中,常常将工具类中的方法,声明为静态方法。比如:Arrays类、Math类

单例 (Singleton)设计模式

单例模式和实现思路(如果我们要让类在一个虚拟机...):

单例(Singleton)设计模式-饿汉式

单例(Singleton)设计模式-懒汉式

单例模式的优点

总结:

1.设计模式概述:
设计模式是在大量的`实践中总结`和`理论化`之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式免去我们自己再思考和摸索.
就像是经典的棋谱,不同的棋局,我们用不同的棋谱。"套路"经典的设计模式一共有23种。2.何为单例模式(Singleton):
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。3.如何实现单例模式(掌握):
> 饿汉式> 懒汉式4.对比两种模式(特点、优缺点)
特点:
> 饿汉式:“立即加载”,随着类的加载,当前的唯一实例就创建了
> 懒汉式:"延迟加载",在需要使用的时候,进行创建。优缺点:
> 饿汉式:(优点)写法简单,由于内存中较早加载,使用更方便、更快。是线程安全的。(缺点)内存中占用时间较长。
> 懒汉式: (缺点)线程不安全 (放到多线程章节时解决)(优点)在需要的时候进行创建,节省内存空间。

实例代码:

//饿汉式
public class BankTest {public static void main(String[] args) {
//        Bank bank1 = new Bank();
//        Bank bank2 = new Bank();Bank bank1 = Bank.getInstance();Bank bank2 = Bank.getInstance();System.out.println(bank1 == bank2); //true}
}
//饿汉式
class Bank {//1.类的构造器石私有化private Bank(){}//2.在类的内部创建当前类的实例//4.此属性也必须声明为static的private static Bank instance = new Bank();//3.使用getXXX()方法获取当前类的实例,必须声明为static的public static Bank getInstance(){return instance;}
}//懒汉式
public class GirlFriendTest {public static void main(String[] args) {GirlFriend test1 = GirlFriend.getInstance();GirlFriend test2 = GirlFriend.getInstance();System.out.println(test1 == test2); //true}
}
class GirlFriend {//1.类的构造器私有化private GirlFriend() {}//2.声明当前类的实例化//4.此属性也必须声明为static的private static GirlFriend instance = null;//3.通过getXXX()获取当前类的实例,如果未创建对象,则在方法内部进行创建public static GirlFriend getInstance(){if(instance == null){instance = new GirlFriend();}return instance;}
}

理解main方法的语法

方式2:使用main()的形参进行传值。
代码:
public class MainDemo {public static void main(String[] args) {for (int i = 0; i < args.length; i++) {System.out.println("hello:" + args[i]);}}
}
命令行的方式传值:在执行命令后空格 写上实参
idea的传值方式

点击编辑配置:

执行结果:

总结:

main()方法的剖析
public static void main(string args[]){}1.理解1: 看做是一个普通的静态方法理解2: 看做是程序的入口,格式是固定的。2.与控制台交互
如何从键盘获取数据?
> 方式1:使用Scanner
> 方式2:使用main()的形参进行传值。命令行的方式传值  idea的传值方式

相关代码:

MainTest 
public class MainTest {public static void main(String[] args) { //程序的入口String[] arr = new String[]{"AA", "BB", "CC"};Main.main(arr);}
}
class Main{public static void main(String[] args) { //看做是普通的静态方法System.out.println("Main的main()的调用");for(int i = 0; i < args.length; i++){System.out.println(args[i]);}/*** Main的main()的调用* AA* BB* CC*/}
}

类的成员之四:代码块

总结:

类的成员之四:代码块回顾:类中可以声明的结构:属性、方法、构造器;代码块(或初始化块)、内部类1.代码块(或初始化块)的作用:
(即初始化类或对象的成员变量)用来初始化类或对象的信息2.代码块的修饰:只能使用static进行修饰。3.代码块的分类:静态代码块:使用static修饰非静态代码块:没有使用static修饰4.具体使用:
4.1 静态代码块:> 随着类的加载而执行> 由于类的加载只会执行一次,进而静态代码块的执行,也只会执行一次> 作用:用来初始化类的信息> 内部可以声明变量、调用属性或方法、编写输出语句等操作。> 静态代码块的执行要先于非静态代码块的执行> 如果声明有多个静态代码块,则按照声明的先后顺序执行> 静态代码块内部只能调用静态的结构(即静态的属性、方法),不能调用非静态的结构(即非静态的属性、方法)
4.2 非静态代码块:> 随着对象的创建而执行> 每创建当前类的一个实例,就会执行一次非静态代码块> 作用:用来初始化对象的信息> 内部可以声明变量、调用属性或方法、编写输出语句等操作。> 如果声明有多个非静态代码块,则按照声明的先后顺序执行>非静态代码块内部可以调用静态的结构(即静态的属性、方法),也可以调用非静态的结构(即非静态的属性、方法)

代码:

(1)声明User类
- 包含属性:userName(String类型),password(String类型),registrationTime(long类型),私有化- 包含get/set方法,其中registrationTime没有set方法- 包含无参构造,- 输出“新用户注册”,- registrationTime赋值为当前系统时间- userName就默认为当前系统时间值,- password默认为"123456"- 包含有参构造(String userName,String password)- 输出“新用户注册”,- registrationTime赋值为当前系统时间,- username和password由参数赋值- 包含public String getInfo()方法,返回:"用户名:xx,密码:xx,注册时间:xx"(2)编写测试类,测试类main方法的代码
UserTest 
public class UserTest {public static void main(String[] args) {User u1 = new User();System.out.println(u1.getInfo());User u2 = new User("Tom","654321");System.out.println(u2.getInfo());System.out.println();User1 u3 = new User1();System.out.println(u3.getInfo());}
}User1 
public class User1 {private String userName;private String password;private long registrationTime; //注册时间public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public long getRegistrationTime() {return registrationTime;}{System.out.println("新用户注册");registrationTime = System.currentTimeMillis(); //获取系统当前时间(距离1970-1-1 00:00:00的毫秒数)}//代码块的使用public User1(){
//        System.out.println("新用户注册");
//        registrationTime = System.currentTimeMillis(); //获取系统当前时间(距离1970-1-1 00:00:00的毫秒数)userName = System.currentTimeMillis() + "";password = "123456";}public User1(String userName, String password) {
//        System.out.println("新用户注册");
//        registrationTime = System.currentTimeMillis(); //获取系统当前时间(距离1970-1-1 00:00:00的毫秒数)this.userName = userName;this.password = password;}public String getInfo(){return "用户名:" + userName + ",密码:" + password + ",注册时间为:" + registrationTime;}
}

Field,属性赋值过程

总结:

可以给类的非静态的属性(即实例变量)赋值的位置有:
① 默认初始化
② 显式初始化 或 ⑤ 代码块中初始化
③ 构造器中初始化
******************************
④ 有了对象以后,通过"对象.属性"或"对象.方法"的方法进行赋值2.执行的先后顺序:
① - ②/⑤ - ③ - ④3.(超纲)关于字节码文件中的<init>的简单说明:(通过插件jclasslib bytecode viewer查看)
> <init>方法在字节码文件中可以看到。每个<init>方法都对应着一个类的构造器。(类中声明了几个构造器就会有几个<init>)
> 编写的代码中的构造器在编译以后就会以<init>方法的方式呈现
> <init>方法内部的代码包含了实例变量的显示赋值、代码块中的赋值和构造器中的代码。
> <init>方法用来初始化当前创建的对象的信息的。4.给实例变量赋值的位置很多,开发中如何选?
> 显示赋值:比较适合于每个对象的属性值相同的场景
> 构造器中赋值:比较适合于每个对象的属性值不相同的场景

相关代码:

public class FieldTest {public static void main(String[] args) {Order o1 = new Order();System.out.println(o1.orderId); //1 ---> 2 ---> 3}
}
class Order {/*** 显式初始化 与 代码块中初始化 可以更换位置* 此时的执行结果是1* 反之执行结果是2* order类的加载有一个系的过程,在初始化之前orderId就已经被默认初始化了,并且默认为0,在后面才开始显示赋值或者代码块赋值*/
//    {
//        orderId = 2;
//    }
//    int orderId = 1;int orderId = 1;{orderId = 2;}//构造器会以init的方式呈现的字节码中//字节码暴露了我们加载的顺序public Order(){super();
//        orderId = 3;}public Order(int orderId){this.orderId = orderId;}//对象调用eat方法之前,类中就已经存在了sleep和eat方法了,所以不会报错public void eat(){sleep();}public void sleep(){}
}

字节码文件:

 两个构造函数,两个init

面试题1:

/*** static A* static B* I'm A Class* HelloA* I'm B Class* HelloB*/
class HelloA {public HelloA() {System.out.println("HelloA");}{System.out.println("I'm A Class");}static{System.out.println("static A");}
}
class HelloB extends HelloA {public HelloB() {System.out.println("HelloB");}{System.out.println("I'm B Class");}static {System.out.println("static B");}
}
public class Test01 {public static void main(String[] args) {new HelloB();}
}

面试题2:

public class Test02 {static int x, y,z;static {int x = 5;x--; //就近原则,操作的是新定义的x}static {x--;}public static void method(){y = z++ + ++z;}public static void main(String[] args) {System.out.println("x = " + x);z--; //-1method(); //-1 + 1 = 0 = y   z: 1System.out.println("result:" + (z + y + ++z));  //1 + 0 + 2 = 3}
}

面试题3:

/*** Base* sub:100* sub* base:70*/
class Base {Base(){method(100);}{System.out.println("Base");}public void method(int i){System.out.println("base:" + i);}
}
class Sub extends Base {Sub(){super.method(70);}{System.out.println("sub");}public void method(int i){System.out.println("sub:" + i);}
}
public class Test03 {public static void main(String[] args) {Sub s = new Sub();}
}

关键字:final

总结:

final关键字的使用1.final的理解:最终的2.final可以用来修饰的结构:类、方法、变量3.具体说明:3.1 final修饰类:表示此类不能被继承。比如:String、stringBuffer、stringBuilder类
3.2 final修饰方法:表示此方法不能被重写比如:0bject类中的getClass()
3.3 final修饰变量:既可以修饰成员变量,也可以修饰局部变量。此时的"变量"其实就变成了"常量",意味着一旦赋值,就不可更改。3.3.1 final修饰成员变量:有哪些位置可以给成员变量赋值?> 显式赋值> 代码块中赋值> 构造器中赋值3.3.2 final修饰局部变量:一旦赋值就不能修改> 方法内声明的局部变量: 在调用局部变量前,一定需要赋值。而且一旦赋值,就不可更改> 方法的形参: 在调用此方法时,给形参进行赋值。而且一旦赋值,就不可更改4.final与static搭配: 修饰成员变量时,此成员变量称为:全局常量。
比如:Math的PI

 相关代码:

public class FinalTest {public static void main(String[] args) {E e = new E();System.out.println(e.MIN_SCORE);//编译不通过
//        e.MIN_SCORE = 1;E e1 = new E(10);
//        e1.LEFT = 11; //不可更改}
}
class E {//成员变量final int MIN_SCORE = 0; //显式赋值final int MAX_SCORE;final int LEFT;
//    final int RIGHT; //不赋值会报错{
//        MIN_SCORE = 1;MAX_SCORE = 100; //代码块赋值}{
//        MAX_SCORE = 1; //编译不通过}public E(){LEFT = 2;}public E(int left){LEFT = left;}//报错
//    public void setRight(int right){
//        RIGHT = right;
//    }
}
class F {public void method(){final int num = 10;
//        num++;//编译报错System.out.println(num);}public void method(final int num){
//        num++; //编译报错System.out.println(num);}
}
final class A {}
//报错,不能被继承
//class B extends A {
//
//}
//class subString extends String {}
class C{public final void method(){}
}
class D extends C{//不能被重写
//    public void method(){
//
//    }
}

面试题:

题目1:排错
public class Something {public int addOne(final int x){return ++x; //会报错,x已被赋值了//return x+1;}
}题目2:排错
public class Something {public static void main(String[] args){Other o = new Other();new Something().addOne(o);}//这个地方final修饰的是o,如果o被重新赋值了的话就会报错//但是i是一个变量,他是用final修饰的public void addOne(final Other o){//o= new Other();o.i++;}
}class Other {public int i:
}

抽象类与抽象方法

 选中这行按alt+enter键,选择实现方法(用于抽象子类重写父类的抽象方法)

弹出要实现的方法确定即可

案例:

Creature 
public abstract class Creature { //生物类public abstract void breath(); //呼吸
}Person 
public abstract class Person extends Creature { //抽象类String name;int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public abstract void eat(); //抽象方法public abstract void sleep(); //抽象方法
}Student 
public class Student extends Person {String school;public Student() {}public Student(String name, int age, String school) {super(name, age);this.school = school;}public void eat(){System.out.println("学生多吃有营养的食物");}public void sleep(){System.out.println("学生要保证充足的睡眠");}@Overridepublic void breath() {System.out.println("学生应该多呼吸新鲜空气");}
}Worker 
//public abstract class Worker extends Person{
//
//}
public abstract class Worker extends Person{@Overridepublic void eat() {System.out.println("工人很辛苦,多吃");}
}AbstractTest 
public class AbstractTest {public static void main(String[] args) {//编译不通过
//        Person p1 = new Person();
//        p1.eat();Student s1 = new Student();s1.eat();//抽象类不能实例化
//        Worker w1 = new Worker();}
}AbstractTest1 
public class AbstractTest1 {//编译不通过
//    private abstract void method(){};
//    public static abstract void method(){};
}

抽象类应用

多态的应用:模板方法设计模式(TemplateMethod)

总结:

抽象类与抽象方法1.案例引入
举例1:Geometric0bject-Circle-Rectangleabstract class Geometric0bject{//几何图形//求面积(只能考虑提供方法的声明,而没有办法提供方法体。所以,此方法适合声明为抽象方法)//求周长(只能考虑提供方法的声明,而没有办法提供方法体。所以,此方法适合声明为抽象方法)
}class Circle extends Geometric0bject {//求面积(必须重写(或实现)父类中的抽象方法)//求周长(必须重写(或实现)父类中的抽象方法)
}举例2:Account-SavingAccount-CheckAcount
class Account{double balance;//余额//取钱 (声明为抽象方法)//存钱 (声明为抽象方法)
}class SavingAccount extends Account{ //储蓄卡//取钱 (需要重写父类中的抽象方法)//存钱 (需要重写父类中的抽象方法)
}class CheckAccount extends Account{ //信用卡//取钱 (需要重写父类中的抽象方法)//存钱 (需要重写父类中的抽象方法)
}//......2.abstract的概念:抽象的3.abstract可以用来修饰:类、方法4.具体的使用:4.1 abstract修饰类:> 此类称为抽象类> 抽象类不能实例化。> 抽象类中是包含构造器的,因为子类对象实例化时,需要直接或间接的调用到父类的构造器。> 抽象类中可以没有抽象方法。反之,抽象方法所在的类,一定是抽象类,(因为需要确保这个方法不能被调用,而方法是需要通过对象来调用,这样干脆让类为抽象类,不能实例化)4.2 abstract修饰方法> 此方法即为抽象方法> 抽象方法只有方法的声明,没有方法体。> 抽象方法其功能是确定的(通过方法的声明即可确定),只是不知道如何具体实现(体现为没有方法体)> 子类必须重写父类中的所有的抽象方法之后,方可实例化。否则,此子类仍然是一个抽象类5.abstract不能使用的场景
5.1 abstract 不能修饰哪些结构?
属性、构造器、代码块等。5.2 abstract 不能与哪些关键字共用? (自洽)
不能用abstract修饰私有方法、静态方法、final的方法、final的类
> 私有方法不能重写
> 避免静态方法使用类进行调用
> final的方法不能被重写
> final修饰的类不能有子类

练习:

编写工资系统,实现不同类型员工(多态)的按月发放工资。如果当月出现某个
Employee对象的生日,则将该雇员的工资增加100元。实验说明:
(1)定义一个Employee类,该类包含:
private成员变量name,number,birthday,其中birthday 为MyDate类的对象;提供必要的构造器
abstract方法earnings();
toString()方法输出对象的name,number和birthday。(2)MyDate类包含:
private成员变量year,month,day ;提供必要的构造器
toDateString()方法返回日期对应的字符串:xxxx年xx月xx日(3)定义SalariedEmployee类继承Employee类,实现按月计算工资的员工处
理。该类包括:private成员变量monthlySalary;
提供必要的构造器;
实现父类的抽象方法earnings(),该方法返回monthlySalary值;toString()方法输
出员工类型信息及员工的name,number,birthday。比如:SalariedEmployee[name = '', number = '', birthday = ''](4)参照SalariedEmployee类定义HourlyEmployee类,实现按小时计算工资的
员工处理。该类包括:
private成员变量wage和hour;
提供必要的构造器;
实现父类的抽象方法earnings(),该方法返回wage*hour值;
toString()方法输出员工类型信息及员工的name,number,birthday。比如:HourlyEmployee[name = '', number = '', birthday = ''](5)定义PayrollSystem类,创建Employee变量数组并初始化,该数组存放各
类雇员对象的引用。利用循环结构遍历数组元素,输出各个对象的类
型,name,number,birthday,以及该对象生日。当键盘输入本月月份值时,如果本
月是某个Employee对象的生日,还要输出增加工资信息。
提示:
//定义People类型的数组People c1[]=new People[10];
//数组元素赋值
c1[0]=new People("John","0001",20);
c1[1]=new People("Bob","0002",19);
//若People有两个子类Student和Officer,则数组元素赋值时,可以使父类类型的数组元素指向子类。
c1[0]=new Student("John","0001",20,85.0);
c1[1]=new Officer("Bob","0002",19,90.5);
TemplateMethodTest 
public class TemplateMethodTest {public static void main(String[] args) {BankTemplateMethod btm = new DrawMonney();btm.process();BankTemplateMethod btm2 = new ManageMonney();btm2.process();}
}
abstract class BankTemplateMethod {//具体方法public void takeNumber(){System.out.println("排队取号");}public abstract void transact();public void evaluate(){System.out.println("反馈评分");}//模板方法,把基本操作组合到一起,子类一般不能重写public final void process(){this.takeNumber();this.transact(); //像个钩子,具体执行时,挂哪个类,就执行哪个子类的实现代码this.evaluate();}
}
class DrawMonney extends BankTemplateMethod {public void transact(){System.out.println("我要取款!!!");}
}
class ManageMonney extends BankTemplateMethod {public void transact(){System.out.println("我要理财!我这里有2000万美元!!");}
}或练习
public class TemplateTest {public static void main(String[] args) {PrintPrimeNumber p = new PrintPrimeNumber();p.spendTime();}
}
abstract class Template {//计算某段代码的执行,需要花费的时间public void spendTime(){long start = System.currentTimeMillis();code();long end = System.currentTimeMillis();System.out.println("花费的时间为:" + (end - start));}public abstract void code();
}
class PrintPrimeNumber extends Template {public void code(){for(int i = 2; i <= 100000; i++){boolean isFlag = true;for(int j = 2; j <= Math.sqrt(i); j++){if(i % j == 0){isFlag = false;break;}}if(isFlag){System.out.println(i);}}}
}

接口(interface)

相关代码:

public class InterfaceTest {public static void main(String[] args) {System.out.println(Flyable.MIN_SPEED);System.out.println(Flyable.MAX_SPEED);//编译报错
//        Flyable.MAX_SPEED = 7800;Bullet b1 = new Bullet();b1.fly();b1.attack();//接口的多态性Flyable f1 = new Bullet();f1.fly(); //编译的时候是接口当中的方法,但是运行的时候是实现类当中的方法}
}
interface Flyable { //接口//全局常量public static final int MIN_SPEED = 0;// 可以省略public static finalint MAX_SPEED = 7900;//方法可以省略public abstract声明
//    public abstract void fly();void fly();
}
interface Attackable { //接口public abstract void attack();
}
abstract class Plane implements Flyable,Attackable {}
class Bullet implements Flyable {public void fly() {System.out.println("让子弹飞一会儿");}public void attack(){System.out.println("子弹可以击穿身体");}
}
//测试接口的继承关系
interface AA {void method1();
}
interface BB{void method2();
}
interface CC extends AA,BB{ //接口可以多继承
}
class DD implements CC {public void method1(){}public void method2(){}
}

练习题:

设备连接

/*** 设备连接成功...* 打印机开始工作* 数据传输的细节操作...* 打印机结束工作* 设备连接成功...* 照相机开始工作* 数据传输的细节操作...* 照相机结束工作* 设备连接成功...* U盘开始工作* 数据传输的细节操作...* U盘开始结束工作* 设备连接成功...* 扫描仪开始工作* 数据传输的细节操作...* 扫描仪结束工作*/
public class USBTest {public static void main(String[] args) {//1.创建接口实现类的对象Computer computer = new Computer();Printer printer = new Printer();computer.transferDate(printer);//2.创建接口实现类的匿名对象computer.transferDate(new Camera());//3.创建接口匿名实现类的对象USB usb1 = new USB(){public void start(){System.out.println("U盘开始工作");}public void stop(){System.out.println("U盘开始结束工作");}};computer.transferDate(usb1);//4.创建接口匿名实现类的匿名对象computer.transferDate(new USB(){public void start(){System.out.println("扫描仪开始工作");}public void stop(){System.out.println("扫描仪结束工作");}});}
}
class Computer {public void transferDate(USB usb){System.out.println("设备连接成功...");usb.start();System.out.println("数据传输的细节操作...");usb.stop();}
}
class Camera implements USB {@Overridepublic void start() {System.out.println("照相机开始工作");}@Overridepublic void stop() {System.out.println("照相机结束工作");}
}
class Printer implements USB {@Overridepublic void start() {System.out.println("打印机开始工作");}@Overridepublic void stop() {System.out.println("打印机结束工作");}
}
interface USB {//声明常量//USB的长、宽、高...//方法public abstract void start();void stop();
}

练习2: 

1、声明接口Eatable,包含抽象方法public abstract void eat();
2、声明实现类中国人Chinese,重写抽象方法,打印用筷子吃饭
3、声明实现类美国人American,重写抽象方法,打印用刀叉吃饭
4、声明实现类印度人Indian,重写抽象方法,打印用手抓饭
5、声明测试类EatableTest,创建Eatable数组,存储各国人对象,并遍历数组,调用eat()方法
Chinese 
public class Chinese implements Eatable {public void eat() {System.out.println("中国人使用筷子吃饭");}
}
American 
public class American implements Eatable {@Overridepublic void eat() {System.out.println("美国人使用刀叉吃饭");}
}
Indian 
public class Indian implements Eatable{@Overridepublic void eat() {System.out.println("印度人使用手抓饭");}
}public interface Eatable {void eat();
}EatableTest 
public class EatableTest {public static void main(String[] args) {Eatable[] eatables = new Eatable[3];eatables[0] = new Chinese(); //多态性eatables[1] = new American();eatables[2] = new Indian();/*** 中国人使用筷子吃饭* 美国人使用刀叉吃饭* 印度人使用手抓饭*/for (int i = 0; i < eatables.length; i++) {eatables[i].eat();}}
}

练习题3:

定义一个接口用来实现两个对象的比较。interface CompareObject{//若返回值是0,代表相等;若为正数,代表当前对象大;负数代表当前对象小public int compareTo(Object o);
}
定义一个Circle类,声明radius属性,提供getter和setter方法定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。
在ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半径大小。定义一个测试类InterfaceTest,创建两个ComparableCircle对象,调用compareTo方法比较两个类的半径大小。拓展:参照上述做法定义矩形类Rectangle和ComparableRectangle类,在ComparableRectangle类
中给出compareTo方法的实现,比较两个炬形的面积大小。
CompareObject 
public interface CompareObject {//若返回值是 0,代表相等,若为正数,代表当前对象大;负数代表当前对象小public int compareTo(Object o);
}Circle 
public class Circle {private double radius; //半径public Circle() {}public Circle(double radius) {this.radius = radius;}public double getRadius() {return radius;}public void setRadius(double radius) {this.radius = radius;}@Overridepublic String toString() {return "Circle{" +"radius=" + radius +'}';}
}ComparableCircle 
public class ComparableCircle extends Circle implements CompareObject {public ComparableCircle() {}public ComparableCircle(double radius) {super(radius);}//根据对象半径的大小,比较对象的大小@Overridepublic int compareTo(Object o) {if(this == o) {return 0;}if(o instanceof ComparableCircle) {ComparableCircle c = (ComparableCircle)o;// 错误的
//            return (int)(this.getRadius() - c.getRadius());//正确的写法1:
//            if(this.getRadius() > c.getRadius()) {
//                return 1;
//            }else if(this.getRadius() < c.getRadius()){
//                return -1;
//            }else {
//                return 0;
//            }//正确的写法2:return Double.compare(this.getRadius(), c.getRadius());}else {return 2; //如果输入的类型不匹配,则返回2
//            throw new RuntimeException("输入的类型不匹配");}}
}
InterfaceTest 
public class InterfaceTest {public static void main(String[] args) {ComparableCircle c1 = new ComparableCircle(2.3);ComparableCircle c2 = new ComparableCircle(5.3);int compareValue = c1.compareTo(c2);if(compareValue > 0){System.out.println("c1对象大");}else if(compareValue < 0){System.out.println("c2对象大");}else{System.out.println("c1和c2一样大");}}
}

接口的应用:代理模式(Proxy)

 总结:

接口的使用1.接口的理解:接口的本质是契约、标准、规范,就像我们的法律一样。制好后大家都要遵守2.定义接口的关键字:interface3.接口内部结构的说明:> 可以声明:属性:必须使用public static final修饰方法:jdk8之前:声明抽象方法,修饰为public abstractjdk8:声明静态方法、默认方法jdk9:声明私有方法> 不可以声明: 构造器、代码块等4.接口与类的关系:实现关系5.格式: class A extends SuperA implements B,C{}
A相较于SuperA来讲,叫做子类
A相较于B,C来讲,叫做实现类。6.满足此关系之后,说明:
> 类可以实现多个接口。
> 类针对于接口的多实现,一定程度上就弥补了类的单继承的局限性。
> 类必须将实现的接口中的所有的抽象方法都重写(或实现),方可实例化。否则,此实现类必须声明为抽象类。7.接口与接口的关系: 继承关系,且可以多继承8.接口的多态性: 接口名 变量名 = new 实现类对象;// 父类 变量名 = new 子类对象; 类的多态性
9.面试题:区分抽象类和接口
> 共性:都可以声明抽象方法都不能实例化
> 不同:① 抽象类一定有构造器。接口没有构造器② 类与类之间继承关系,类与接口之间是实现关系,接口与接口之间是多继承关系

相关代码 :

CompareA 
public interface CompareA {//属性:声明为public static final//方法:jdk8之前,只能声明抽象方法//方法:jdk8中:静态方法public static void method1(){System.out.println("CompareA:北京");}//方法:jdk8中:默认方法
//    public void method3(); //这种写法是抽象方法,不是抽象方法就需要抽象体public default void method2(){System.out.println("CompareA:上海");};public default void method3(){System.out.println("CompareA:广州");};public default void method4(){System.out.println("CompareA:深圳");};//jdk9新特性:定义私有方法private void method5(){System.out.println("我是接口中定义的私有方法");}
}
CompareB 
public interface CompareB {public default void method3(){System.out.println("CompareB: 广州");}
}
SuperClass 
public class SuperClass {public void method4() {System.out.println("SuperClass:深圳");}
}
SubClassTest 
public class SubClassTest {public static void main(String[] args) {//知识点1:接口中声明的静态方法只能被接口来调用,不能使用期实现类进行调用CompareA.method1();
//        SubClass.method1(); //编译不通过//默认方法涉及到造对象,重写之后调用的是重写之后的方法//知识点2:接口中声明的默认方法可以被类继承,实现类在没有重写此方法的情况下,默认调用接口中声明的//默认方法,如果实现类重写了此方法,则调用的是自己重写的方法SubClass s1 = new SubClass();s1.method2();//知识点3:类实现了两个接口,而两个接口中定义了同名同参数的默认方法,则实现类在没有重写此两个接口//默认方法的情况下,或报错,--->接口冲突//要求:此时实现类必须要重写接口中定义的同名同参数的方法s1.method3();//知识点4:子类(或实现类)继承了父类并实现了接口,父类和接口中声明了同名同参数的方法,(其中,接口中的方法//是默认方法)。默认情况下,子类(或实现类)在没有重写此方法的情况下,调用的是父类中的方法。---> 类优先原则/*** CompareA:北京* SubClass:上海* SubClass:广州* SuperClass:深圳 ---> SubClass:深圳(子类重写之后)*/s1.method4();}
}
SubClass 
public class SubClass extends SuperClass implements CompareA, CompareB {@Overridepublic void method2() {System.out.println("SubClass:上海");}@Overridepublic void method3() {System.out.println("SubClass:广州");}public void method4() {System.out.println("SubClass:深圳");}public void method(){//知识点5:如何在子类(或实现类)中调用父类或接口中重写的方法method4(); //调用自己类中的方法super.method4();method3(); //调用自己类中的方法
//        CompareA.method1(); //静态方法可以这样调用,不是静态的方法按照下面的方式调用CompareA.super.method3(); //调用接口CompareA中的默认方法CompareB.super.method3(); //调用接口CompareB中的默认方法}
}

类的成员之五:内部类

内部类生成的文件通过 $内部类名 来表示

代码示例:

public class OuterClassTest {public static void main(String[] args) {//1.创建Person的静态的成员内部类的实例Person.Dog dog = new Person.Dog();dog.eat();//2.创建Person的非静态的成员内部类的实例
//        Person.Bird bird = new Person.Bird(); //报错Person p1 = new Person();Person.Bird bird = p1.new Bird(); //正确的bird.eat();bird.show("黄鹂");bird.show1();}
}
class Person { //外部类String name = "Tom";int age = 1;//静态的成员内部类static class Dog{public void eat() {System.out.println("狗吃骨头");}}//非静态的成员内部类class Bird{String name = "啄木鸟";public void eat(){System.out.println("鸟吃虫子");}public void show(String name){System.out.println("age = " + age); //age = 1 省略了Person.thisSystem.out.println("name = " + name); //name = 黄鹂System.out.println("name = " + this.name); //name = 啄木鸟System.out.println("name = " + Person.this.name); //name = Tom}public void show1(){eat(); //鸟吃虫子this.eat(); //鸟吃虫子Person.this.eat(); //人吃饭}}public void eat(){System.out.println("人吃饭");}public void method(){//局部内部类class innerClass1{}}public Person(){//局部内部类class innerClass1{}}{//局部内部类class innerClass1{}}
}

代码示例2:

public class OuterClassTest1 {//说明:局部内部类的使用public void method1(){//局部内部类class A{//可以声明属性、方法等}}//开发中的场景public Comparable getInstance(){//提供了实现了Comparable接口的类//方式1:提供了接口的实现类的对象
//        class MyComparable implements Comparable{
//
//            @Override
//            public int compareTo(Object o) {
//                return 0;
//            }
//        }
//        MyComparable m = new MyComparable();
//        return m;//方式1:提供了接口的实现类的匿名对象
//        class MyComparable implements Comparable{
//
//            @Override
//            public int compareTo(Object o) {
//                return 0;
//            }
//        }
//        return new MyComparable();//方式2:提供了接口的匿名实现类的对象//后面的大括号表示实现类
//        Comparable c = new Comparable() {
//            @Override
//            public int compareTo(Object o) {
//                return 0;
//            }
//        };
//        return c;//方式3:提供了接口的匿名实现类的匿名对象return new Comparable(){@Overridepublic int compareTo(Object o) {return 0;}};}
}

代码示例3:

public class OuterClassTest2 {public static void main(String[] args) {SubA a = new SubA();a.method();//举例1:提供了接口匿名实现类的对象A a1 = new A(){public void method() {System.out.println("匿名实现类重写的方法method()");}};a1.method();//举例2:提供了接口匿名实现类的匿名对象new A(){public void method() {System.out.println("匿名实现类重写的方法method()");}}.method();//举例3:SubB s1 = new SubB();s1.method1();//举例4:提供了继承于抽象类的匿名子类的对象B b = new B() {@Overridepublic void method1() {System.out.println("继承于抽象类的子类调用的方法");}};b.method1();System.out.println(b.getClass()); //class com.atguigu09.inner.OuterClassTest2$3System.out.println(b.getClass().getSuperclass()); //class com.atguigu09.inner.B//举例5:new B(){@Overridepublic void method1() {System.out.println("继承于抽象类的子类调用的方法1");}}.method1();//举例6:C c = new C();c.method2();//举例7:提供了一个继承于C的匿名子类的对象
//        C c1 = new C(){};C c1 = new C(){public void method2() {System.out.println("SubC");}};c1.method2();
//        System.out.println(c.getClass());//class com.atguigu09.inner.C
//        System.out.println(c1.getClass().getSuperclass());//class com.atguigu09.inner.C}
}
interface A{public void method();
}
class SubA implements A{public void method(){System.out.println("SubA");}
}
abstract class B{public abstract void method1();
}
class SubB extends B{public void method1(){System.out.println("SubB");}
}
class C{public void method2(){System.out.println("C");}
}

练习1:

编写一个匿名内部类,它继承Object,并在匿名内部类中,声明一个方法public void test()打印尚硅谷。
请编写代码调用这个方法。
public class ObjectTest {public static void main(String[] args) {
//        SubObject sub1 = new SubObject();
//        sub1.test();//提供一个继承于Object的匿名子类的匿名对象new Object(){public void test(){System.out.println("尚硅谷");}}.test();}
}
class SubObject extends Object{public void test(){System.out.println("尚硅谷");}
}

native关键字的理解: 

枚举类enum

单例模式当中有饿汉式与懒汉式

总结:

枚举类的使用
1.枚举类的理解:枚举类型本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。
2.举例:
- 星期:Monday(星期一)......Sunday(星期天)
- 性别:Man(男)、Woman(女)
- 月份:January(1月)......December(12月)
- 季节:Spring(春节)......Winter(冬天)
- 三原色:red(红色)、green(绿色)、blue(蓝色)
- 支付方式:Cash(现金)、WechatPay(微信)、Alipay(支付宝)、BankCard(银行卡)、Creditcard(信用卡)
- 就职状态:Busy(忙碌)、Free(空闲)、Vocation(休假)、Dimission(离职)
- 订单状态:Nonpayment(未付款)、Paid(已付款)、Fulfilled(已配货)、Delivered(已发货)、checked(已确认收货)、Return(退货)、Exchange(换货)、Cancel(取消)
- 线程状态:创建、就绪、运行、阻塞、死亡3.开发中的建议:
> 开发中,如果针对于某个类,其实例是确定个数的,则推荐将此类声明为枚举类
> 如果枚举类的实例只有一个,则可以看做是单例的实现方式。4.JDK5.0 之前如何自定义枚举类(了解)
见代码
5.JDK5.0中使用enum定义枚举类
见代码
6.Enum中的常用方法:
6.1 使用enum关键字定义的枚举类,默认其父类是java.lang.Enum类使用enum关键字定义的枚举类,不要再显示的定义其父类。否则报错
6.2 熟悉Enum类中常用的方法string toString():默认返回的是常量名(对象名),可以继续手动重写该方法!(关注)static 枚举类型[] valves():返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值,是一个静态方法(关注)static 枚举类型 value0f(String name):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的"名字"。如不是,会有运行时异常:IllegalArgumentException。String name():得到当前枚举常量的名称。建议优先使用toString()。int ordinal():返回当前枚举常量的次序号,默认从0开始
7.枚举类实现接口的操作情况1:枚举类实现接口,在枚举类中重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是同一个方法。情况2:让枚举类的每一个对象重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是不同的实现的方法。

相关代码1:

public class SeasonTest {public static void main(String[] args) {
//        Season.AUTUMN = null; //报错System.out.println(Season.SPRING);System.out.println(Season.SUMMER.getSeasonName());System.out.println(Season.SUMMER.getSeasonDesc());}
}
//jdk5.0之前定义的枚举方式
class Season{//2.声明当前类的对象的实例变量,使用private final修饰private final String seasonName; //季节的名称private final String seasonDesc; //季节的描述//1.私有化类的构造器private Season(String seasonName, String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}//3.提供实例变量的get方法public String getSeasonName(){return seasonName;}public String getSeasonDesc(){return seasonDesc;}//4.创建当前类的实例,使用public static final修饰public static final Season SPRING = new Season("春天", "春暖花开");public static final Season SUMMER = new Season("夏天", "夏日炎炎");public static final Season AUTUMN = new Season("秋天", "秋高气爽");public static final Season WINTER = new Season("冬天", "白雪皑皑");@Overridepublic String toString() {return "Season{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}
}

相关代码2:

public class SeasonTest1 {public static void main(String[] args) {
//        System.out.println(Season1.SPRING.getClass()); //class com.atguigu10._enum.Season1
//        System.out.println(Season1.SPRING.getClass().getSuperclass()); //class java.lang.Enum
//        System.out.println(Season1.SPRING.getClass().getSuperclass().getSuperclass()); //class java.lang.Object//测试方法//1.toString()System.out.println(Season1.SPRING); //SPRING(toString()重写之前)//2.name()System.out.println(Season1.SPRING.name()); //SPRING//3.values()Season1[] values = Season1.values();/*** Season1{seasonName='春天', seasonDesc='春暖花开'}* Season1{seasonName='夏天', seasonDesc='夏日炎炎'}* Season1{seasonName='秋天', seasonDesc='秋高气爽'}* Season1{seasonName='冬天', seasonDesc='白雪皑皑'}*/for(int i=0; i<values.length; i++){System.out.println(values[i]);}//4.valueOf(String objName):再返回当前枚举类中名称为objName的枚举对象//如果枚举类不存在objName名称的对象,则报错String objName = "WINTER";
//        objName = "WINTER1"; //报错IllegalArgumentExceptionSeason1 season1 = Season1.valueOf(objName);System.out.println(season1);//5.ordinal()System.out.println(Season1.AUTUMN.ordinal()); //2//通过枚举类的对象调用重写后的接口中的方法Season1.AUTUMN.show();}
}
interface Info{void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 implements Info{//1.必须在枚举类的开头声明多个对象,对象之间使用,隔开SPRING("春天", "春暖花开"),SUMMER("夏天", "夏日炎炎"),AUTUMN("秋天", "秋高气爽"),WINTER("冬天", "白雪皑皑");//2.声明当前类的对象的实例变量,使用private final修饰private final String seasonName; //季节的名称private final String seasonDesc; //季节的描述//3.私有化类的构造器private Season1(String seasonName, String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}//3.提供实例变量的get方法public String getSeasonName(){return seasonName;}public String getSeasonDesc(){return seasonDesc;}@Overridepublic String toString() {return "Season1{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}@Overridepublic void show() {System.out.println("这是一个季节");}
}改进2
public class SeasonTest2 {public static void main(String[] args) {Season2[] values = Season2.values();for(int i = 0; i < values.length; i++){
//            System.out.println(values[i]);values[i].show();}}
}
interface Info1{void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season2 implements Info1{//1.必须在枚举类的开头声明多个对象,对象之间使用,隔开SPRING("春天", "春暖花开"){public void show(){System.out.println("春天在哪里?");}},SUMMER("夏天", "夏日炎炎"){public void show(){System.out.println("宁静的夏天");}},AUTUMN("秋天", "秋高气爽"){public void show(){System.out.println("秋意浓");}},WINTER("冬天", "白雪皑皑"){public void show(){System.out.println("大约在冬季");}};//2.声明当前类的对象的实例变量,使用private final修饰private final String seasonName; //季节的名称private final String seasonDesc; //季节的描述//3.私有化类的构造器private Season2(String seasonName, String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}//3.提供实例变量的get方法public String getSeasonName(){return seasonName;}public String getSeasonDesc(){return seasonDesc;}@Overridepublic String toString() {return "Season1{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}
}

就职状态代码:

Employee 
public class Employee {private String name;private int age;private Status status;public Employee() {}public Employee(String name, int age, Status status) {this.name = name;this.age = age;this.status = status;}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 Status getStatus() {return status;}public void setStatus(Status status) {this.status = status;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", age=" + age +", status=" + status +'}';}
}
枚举:
public enum Status {BUSY,FREE,VOCATION,DIMISSION;
}
EmployeeTest 
public class EmployeeTest {public static void main(String[] args) {Employee e1 = new Employee("Tom", 21, Status.BUSY);System.out.println(e1); //Employee{name='Tom', age=21, status=BUSY}}
}
案例:使用枚举类实现单例模式
public class BnakTest1 {public static void main(String[] args) {
//        Bank1.instance = null; //final可以用但不能修改System.out.println(GirlFriend.XIAL_LI); //XIAL_LI}
}
//jdk5.0之前的使用枚举类定义单例模式
class Bank1 {//饿汉式
//    private Bank1(){}
//    private static Bank1 instance = new Bank1();
//    public static Bank1 getInstance(){
//        return instance;
//    }//枚举类没有通过方法调用,而是直接通过类来调用private Bank1(){}private static final Bank1 instance = new Bank1();
}
//jdk5.0使用enum关键字定义枚举类的方式定义单例模式
enum Bank2{CPB;
}
enum GirlFriend{
//    public static final GirlFriend XIAL_LI = new GirlFriend(20); //之前写法XIAL_LI(20);private final int age;private GirlFriend(int age){this.age = age;}
}

案例: 

案例拓展:颜色枚举类(使用enum声明)
(1)声明颜色枚举类Color:
- 声明final修饰的int类型的属性red,green,blue
- 声明final修饰的String类型的属性description
- 声明有参构造器Color(int red,int green,int blue,String description)
- 创建7个常量对象:红、橙、黄、绿、青、蓝、紫,
- 重写toString方法,例如:RED(255,0,0)->红色
(2)在测试类中,使用枚举类,获取绿色对象,并打印对象。
提示:
- 7个常量对象的RGB值如下:
红:(255,0,0)
橙:(255,128,0)
黄:(255,255,0)
绿:(0,255,0)
青:(0,255,255)
蓝:(0,0,255)
紫:(128,0,255)7个常量对象名如下
RED, ORANGE,YELLOW, GREEN,CYAN, BLUE,PURPLE
public class ColorTest {public static void main(String[] args) {System.out.println(Color.BLUE);}
}
enum Color {RED(255,0,0,"红色"),ORANGE(255,128,0,"橙色"),YELLOW(255,255,0,"黄色"),GREEN(0,255,0,"绿色"),CYAN(0,255,255,"青色"),BLUE(0,0,255,"蓝色"),PURPLE(128,0,255,"紫色");private final int red;private final int green;private final int blue;private final String description; //颜色的描述Color(int red, int green, int blue, String description) {this.red = red;this.green = green;this.blue = blue;this.description = description;}public int getRed() {return red;}public int getGreen() {return green;}public int getBlue() {return blue;}public String getDescription() {return description;}@Overridepublic String toString() {
//        return name()+ "(" + red + "," + green + "," + blue + ")" + "--->" + description;return super.toString()+ "(" + red + "," + green + "," + blue + ")" + "--->" + description;}
}

annotation注解的使用

`@SuppressWarnings`:抑制编译器警告

移动到元素上,选择更多操作

结果如下:  @SuppressWarnings("unused") int num = 10;

JUnit单元测试

怎么添加单元测试包,通过+号选择库(library)

务必选择编译

就可以为当前模块(module)添加单元测试(junit)

也可以通过选中当前@Test这个测试类,按住alt+enter回车键,在有网的情况下下载包

默认情况下,单元测试方法中使用Scanner失效。如何解决?

在单元测试里面如果没有做什么配置,在这个地方输入什么都无法显示

如果不想是只读的,输入的数值可以显示出来,在help里面选择编辑自定义虚拟机选项

在这个文件中将这一句话加上:-Deditable.java.test.console=true

之后在文件地方选择使缓存失效

点击重启,或者直接关闭idea,重新打开也可

此时再输入数值就可以正常显示了

结果显示:

如何将将单元测试设置成一个模板?

使用模板,在光标出输入需要输入的值

总结和相关代码:

JUnit单元测试的使用
1.需要导入的jar包:
junit-4.12.jar
hamcrest-core-1.3.jar
2.导入步骤
见课件
3.创建单元测试类,进行测试
见代码
4.(重点关注)要想能正确的编写单元测试方法,需要满足:
- 所在的类必须是public的,非抽象的,包含唯一的无参构造器。
- @Test标记的方法本身必须是public,非抽象的,非静态的,void无返回值,()无参数的。
5.默认情况下,单元测试方法中使用Scanner失效。如何解决?6.大家可以将单元测试设置成一个模板?
public class JunitTest { //单元测试类public static void main(String[] args) {//静态方法调用非静态方法需要进行测试JunitTest test = new JunitTest();System.out.println(test.number);test.method();}int number = 10;@Testpublic void test1() { //单元测试方法System.out.println("Hello");}@Testpublic void test2() {System.out.println("Hello1");System.out.println("number = " + number);method();int num = showInfo("China");System.out.println(num);}public void method() {System.out.println("method()......");}public int showInfo(String info){System.out.println(info);return 10;}@Testpublic void test3() {Scanner sc = new Scanner(System.in);System.out.println("请输入一个数值");int num = sc.nextInt();System.out.println(num);for(int i = 1; i <= num; i++){System.out.println(i);}}@Testpublic void test4(){System.out.println("Hello4");}@Testpublic void test5(){System.out.println("Hello5");}
}

包装类(Wrapper)的使用

基本类型、包装类与String类间的转换

字节码文件可以体现出自动装箱与自动拆箱的过程

包装类缓存对象

面试题1:

public class InterviewTest1 {public static void main(String[] args) {Integer i = new Integer(1);Integer j = new Integer(1);System.out.println(i == j); // false//底层都会调用Integer的valueOf()//这个地方取得值是里面已经new好的Integer数组里面的对象,cache数组中每一个位置都是一个new Integer()对象,//所以他们的地址值都是相同的,都是取的cache数组中的第129位Integer m = 1; //自动装箱Integer n = 1;System.out.println(m == n); //true//根据valueOf的源码可知,这个地方的128不在[-128,127]范围内,所以是new Integer(i)的一个对象出来Integer x = 128;Integer y = 128;System.out.println(x == y); //false}
}

cache数组长度是256,循环,cache数组[第一位是-128,第二位是-127.....一直到127]为止

用自动装箱的方式,在这个范围内用==判断的全都是true,出了这个范围是false

面试题2:

public class InterviewTest2 {public static void main(String[] args) {//题目1:int i = 10;double d = 10.2;System.out.println(i == d); //false//题目2:Integer i1 = 10;Double d1 = 10.2;
//        System.out.println(i1 == d1); //报错,==可以比较引用类型的地址,但是需要时同一类型//题目3:会进行拆箱,m就会转成int类型的,装箱会成为不同引用类型,会报错Integer m = 1000; //1000先装箱,比较时拆箱double n = 1000;System.out.println(m == n); //true//题目4:Integer x = 1000;int y = 1000;System.out.println(x == y); // true}
}

int(i)类型转换成(to)成double类型(d)  i2d

面试题3:

public class InterviewTest3 {public static void main(String[] args) {//这个地方的比较有一个类型兼容的问题,所以输出结果是1.0Object o1 = true ? new Integer(1) : new Double(2.0);System.out.println(o1); //1.0Object o2;if(true)o2 = new Integer(1);elseo2 = new Double(2.0);System.out.println(o2); //1}
}

总结:

包装类的使用
1.为什么要使用包装类?
为了使得基本数据类型的变量具备引用数据类型变量的相关特征(比如:封装性、继承性、多态性),我们给各个基本数据
类型的变量都提供了对应的包装类。
2.(掌握)基本数据类型对应的包装类类型byte -> Byteshort -> Shortint -> Integerlong -> Longfloat -> Floatdouble ->Doublechar -> Characterboolean -> Boolean
3.掌握基本数据类型 与 包装类之间的转换。3.1 为什么需要转换> 一方面,在有些场景下,需要使用基本数据类型对应的包装类的对象。此时就需要将基本数据类型的变量转换为包装类的对象。比如:ArrayList的add(Object obj);Object类的equals(Object obj)> 对于包装类来讲,既然我们使用的是对象,那么对象是不能进行+ - * /等运算的。为了能够进行这些运算,就需要将包装类的对象转换为基本数据类型的变量。3.2 如何转换:(装箱)基本数据类型 ---> 包装类: ① 使用包装类的构造器 ② (建议)调用包装类的valueOf(xxxxx)(拆箱)包装类 ---> 基本数据类型: 调用包装类的xxxValue()注意:原来使用基本数据类型变量的位置,改成包装类以后,对于成员变量来说,其默认值变化了!jdk5.0新特性:自动装箱、自动拆箱。4.String 与 基本数据类型、包装类之间的转换。基本数据类型、包装类---> String类型: ① String类型:调用String的重载的静态方法value0f(xxxxx); ② 基本数据类型的变量 + ""String类型 ---> 基本数据类型、包装类:调用包装类的静态方法:parseXxx()

相关代码:代码练习

public class WrapperTest {/*** 基本数据类型 ---> 包装类: ① 使用包装类的构造器 ② (建议)调用包装类的value0f(xxx xx)* 包装类 ---> 基本数据类型: 调用包装类的xxxValue()* jdk5.0新特性:自动装箱、自动拆箱。*/@Testpublic void test4(){//自动装箱: 基本数据类型--->包装类int i1 = 10;Integer ii1 = i1;//自动装箱System.out.println(ii1.toString());Integer ii2 = i1 + 1; //自动装箱Boolean bb1 = true;//自动装箱Float f1 = 12.3F;//自动装箱//自动拆箱:包装类---> 基本数据类型int i2 = ii1; //自动拆箱boolean b1 = bb1; //自动拆箱}@Testpublic void test3(){Account account = new Account();System.out.println(account.isFlag1); //falseSystem.out.println(account.isFlag2); //nullSystem.out.println(account.balance1); //0.0System.out.println(account.balance2); //null}@Testpublic void test2(){Integer ii1 = new Integer(10);int i1 = ii1.intValue();i1 = i1 + 1;Float ff1 = new Float(12.3F);float f1 = ff1.floatValue();Boolean bb1 = Boolean.valueOf(true);Boolean b1 = bb1.booleanValue();}@Test//基本数据类型 ---> 包装类: ① 使用包装类的构造器 ② (建议)调用包装类的value0f(xxx xx)public void test1(){int i1 = 10;Integer ii1 = new Integer(i1);System.out.println(ii1.toString()); //10float f1 = 12.3F;f1 = 32.2f;Float ff1 = new Float(f1);System.out.println(ff1.toString()); //32.2String s1 = "32.1";Float ff2 = new Float(s1);//        s1 = "abc";
//        Float ff3 = new Float(s1); //报异常:NumberFormatExceptionboolean b1 = true;Boolean bb1 = new Boolean(b1);System.out.println(bb1);//true//Boolean这块只要长的跟true不一样就是false了String s2 = "false";s2 = "False123";s2 = "TrUe"; //忽略大小写Boolean bb2 = new Boolean(s2);System.out.println(bb2); //false --> true//推荐使用int i2 = 10;Integer ii2 = Integer.valueOf(i2);Boolean b2 = Boolean.valueOf(true);Float f2 = Float.valueOf(12.3F);}
}
class Account{boolean isFlag1;Boolean isFlag2; //null 包装类double balance1; //0.0Double balance2; //null 包装类 0.0可以理解成这个对象被初始化了
}

相关代码2:

public class WrapperTest1 {/*** 基本数据类型、包装类---> ① String类型:调用String的重载的静态方法value0f(xxxxx); ② 基本数据类型的变量 + ""* String类型 ---> 基本数据类型、包装类:调用包装类的静态方法:parseXxx()*/@Testpublic void test2(){String s1 = "123";int i1 = Integer.parseInt(s1);System.out.println(i1 + 10);String s2 = "true";boolean b1 = Boolean.parseBoolean(s2);//特别的
//        String s3 = "123a";
//        int i2 = Integer.parseInt(s3); //报错NumberFormatException}@Testpublic void test1(){//方式1:① String类型:调用String的重载的静态方法value0f(xxxxx); ② 基本数据类型的变量 + ""int i1 = 10;String str1 = String.valueOf(i1);System.out.println(str1); //"10"boolean b1 = true;Boolean b2 = b1;String str2 = String.valueOf(b1);String str3 = String.valueOf(b2);//方式2:基本数据类型的变量 + ""String str4 = i1 + "";String str5 = b1 + "";}
}

练习题:

利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,并输出学生成绩等级。
提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的长度。而向量类java.util.Vector可以根据需要动
1、创建Vector对象:Vector v=new Vector();
2、给向量添加元素:v.addElement(Object obj);//obj必须是对象
3、取出向量中的元素:Object obj=v.elementAt(0);注意第一个元素的下标是0,返回值是0bject类型的。
4、计算向量的长度:v.size();
5、若与最高分相差10分内:A等;20分内:B等;30分内:C等;其它:D等
package com.atguigu12.wrapper.exer;import java.util.Scanner;
import java.util.Vector;/*** ClassName: ScoreTest* Package: com.atguigu12.wrapper.exer* Description:** @Author: shkstart* @Create 2025-03-25 23:46* @Version: 1.0*/
public class ScoreTest {public static void main(String[] args) {//1.创建Vector对象:Vector v= new Vector();Vector v= new Vector();Scanner scanner = new Scanner(System.in);int maxScore = 0; //记录最高分//2.从键盘中获取学生成绩,存放到v中(以负数代表输入结果)while(true){System.out.print("请输入学生成绩(以负数代表输入结束):");int intScore =  scanner.nextInt();if(intScore < 0){break;}
//            //装箱:int ---> Integer对象
//            Integer score = Integer.valueOf(intScore);
//            //添加学生成绩到容器v中
//            v.addElement(score);//jdk5.0之后,自动装箱v.addElement(intScore);//3.获取学生成绩的最大值if(maxScore < intScore){maxScore = intScore;}}System.out.println("最高分:" + maxScore);//4.依次获取v中的每个学生成绩,与最高分进行比较,获取学生等级,进行输出for(int i = 0; i < v.size(); i++){Object objScore = v.elementAt(i);//方式1:
//            Integer integerScore = (Integer)objScore;
//            //拆箱
//            int score = integerScore.intValue();//方式2:自动拆箱int score = (Integer)objScore;char grade = ' ';if(maxScore - score <= 10){grade = 'A';}else if(maxScore - score <= 20){grade = 'B';}else if(maxScore - score <= 30){grade = 'C';}else {grade = 'D';}System.out.println("student " + i + " score: " + score + " grade: " + grade);}scanner.close();}
}

ctrl+fn+f12或ctrl+f12在当前文件进行搜索,搜索内容可以直接输入

IDEA断点调试

Person p1 = new Person(3);
System.out.println(p1.toString());  

toString()没有重写之前打印的是地址,对于引用数据类型来说,重写之后,打印的是重写之后的方法

总结:

IDEA中调试程序
1.为什么需要Debug?
编好的程序在执行过程中如果出现错误,该如何查找或定位错误呢?简单的代码直接就可以看出来,
但如果代码比较复杂,就需要借助程序调试工具(Debug)来查找错误了。
2. Debug的步骤1、添加断点2、启动调试3、单步执行4、观察变量和执行流程,找到并解决问题
Description:演示1:行断点,测试debug各个常见操作按钮
Description: 演示2: 方法断点
Description:演示3:字段断点
Description:演不4:条件断点

Description:演示7:强制结束

复习:

//底层都会调用Integer的valueOf()
//这个地方取得值是里面已经new好的Integer数组里面的对象,cache数组中每一个位置都是一个new Integer()对象,
//所以他们的地址值都是相同的,都是取的cache数组中的第129位
//享元设计模式
Integer m = 1; //自动装箱
Integer n = 1;
System.out.println(m == n); //true

相关文章:

java学习笔记7——面向对象

关键字&#xff1a;static 类变量 静态变量的内存解析&#xff1a; 相关代码&#xff1a; public class ChineseTest {public static void main(String[] args) {System.out.println(Chinese.nation); //null 没赋值前System.out.println(Chinese.nation); //中国 静态变量赋值…...

java学习——函数式编程(1)

函数式编程 Java 的函数式编程是一种以函数为核心构建逻辑的编程范式,强调不可变性、声明式代码和无副作用的操作。它通过Lambda表达式、函数式接口(如Function、Predicate、Consumer等)和Stream API等特性实现,将计算过程抽象为函数的组合与转换,而非传统的命令式步骤。…...

java 批量下载doc\excle\pdf

指定图片集合 下载到指定文件夹 import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.Arrays; import java.util.List;public class OfficeFileDownloader {/*** 需要下载的Office文档URL列表*/private static final List<Strin…...

Python爬虫:Feapder 的详细使用和案例

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 1. Feapder 概述1.1 Feapder介绍1.2 Feapder 核心特点1.3 Feapder 主要组件1.4 Feapder的安装2. 基础爬虫编写2.1 创建爬虫2.2 运行爬虫3. 数据采集案例3.1 新闻网站采集3.2 电商商品采集3.3 使用 Spider 类创建更强大爬…...

【江协科技STM32】读写备份寄存器RTC实时时钟(学习笔记)

参考相关文章理解&#xff1a; 【江协科技STM32】Unix时间戳&#xff08;学习笔记&#xff09;-CSDN博客 【江协科技STM32】BKP备寄存器&RTC实时时钟&#xff08;学习笔记&#xff09;_stm32断电保存时钟-CSDN博客 读写备份寄存器 接线图&#xff1a;VBAT是从STLINK的…...

Linux touch命令

参考资料 Linux 常用命令 - touch 【创建空文件与修改时间戳】 目录 一. 用法简介二. 配合扩展字符&#xff0c;批量创建文件三. 修改文件的时间戳3.1 -t 配置项3.2 -d 配置项3.3 配合find命令实现批量时间戳修改 四. 结合 find 批量创建相同时间的新文件 一. 用法简介 ⏹当指…...

PyTorch图像预处理--Compose

torchvision.transforms.Compose 是 PyTorch 中用于图像预处理的核心工具&#xff0c;可将多个图像变换操作组合成一个顺序执行的流水线。 ‌1. 定义与作用‌ ‌功能‌&#xff1a;将多个图像处理步骤&#xff08;如缩放、裁剪、归一化等&#xff09;串联为一个整体&#xff…...

CSP历年题解

CSP历年题解 csp历年题解&#xff0c;csp.cpp内容涵盖从2023年12月开始一直持续到第一次认证的所有前4题。所有的题解均为满分&#xff0c;在其中&#xff0c;有四道题非本人编写&#xff0c;而从网上搜集优质解答&#xff0c;并且已在文中附上了来源链接。其余则为自己编写&a…...

《索引江湖:B树索引与哈希索引的风云对决》

在数据库的神秘世界里&#xff0c;索引宛如一把把神奇的钥匙&#xff0c;帮助我们在海量数据中快速找到所需信息。而B树索引与哈希索引&#xff0c;则是其中两把最为耀眼的利刃&#xff0c;各自凭借独特的“武功秘籍”&#xff0c;在不同的应用场景中大放异彩。今天&#xff0c…...

java八股文之JVM

1.什么是程序计数器 程序计数器是 JVM 管理线程执行的“定位器”&#xff0c;记录每个线程当前执行的指令位置&#xff0c;确保程序流程的连续性和线程切换的准确性。线程私有的&#xff0c;每个线程一份&#xff0c;内部保存的字节码的行号。用于记录正在执行的字节码指令的地…...

学习爬虫的第二天——分页爬取并存入表中

阅读提示&#xff1a;我现在还在尝试爬静态页面 一、分页爬取模式 以豆瓣Top250为例&#xff1a; 基础url:豆瓣电影 Top 250https://movie.douban.com/top250 分页参数:?start0&#xff08;第一页&#xff09;、?start25&#xff08;第二页&#xff09;等 每页显示25条数…...

Ubuntu与Windows之间相互复制粘贴的方法

一、打开Ubuntu终端 二、卸载已有的工具 sudo apt-get autoremove open-vm-tools 三、安装工具 sudo apt-get install open-vm-tools-desktop 四、重启 直接输入reboot 注&#xff1a;有任何问题欢迎评论区交流讨论或者私信&#xff01;...

docker安装hyperf环境,连接本机redis问题处理

错误信息显示“Connection refused”&#xff0c;这通常说明 Docker 容器内的 Hyperf 项目无法连接到你本机的 Redis 服务。 1. 容器内的 127.0.0.1 指向问题 在 Docker 容器中&#xff0c;127.0.0.1 指的是容器本身&#xff0c;而不是宿主机&#xff08;你的 Mac&#xff09;…...

第12章:优化并发_《C++性能优化指南》notes

优化并发 一、并发基础与优化核心知识点二、关键代码示例与测试三、关键优化策略总结四、性能测试方法论多选题设计题答案与详解多选题答案&#xff1a; 设计题答案示例 一、并发基础与优化核心知识点 线程 vs 异步任务 核心区别&#xff1a;std::thread直接管理线程&#xf…...

Linux操作系统7- 线程同步与互斥7(RingQueue环形队列生产者消费者模型改进)

上篇文章&#xff1a;Linux操作系统7- 线程同步与互斥6&#xff08;POSIX信号量与环形队列生产者消费者模型&#xff09;-CSDN博客 本篇代码仓库&#xff1a;myLerningCode/l36 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 目录 一. 单生产单消费单保…...

学有所记——初探向量数据库Weaviate

目标&#xff1a; 了解向量数据库的连接、建库、插入数据、查询数据等基本用法以及关于语义相似度的一些基本概念。 背景&#xff1a; 前段时间尝试在自己的电脑上搭建OllamaDify平台&#xff0c;体验并探索大模型的强大功能。在使用过程中&#xff0c;尤其是在搭建RAG知识库…...

Ardupilot开源无人机之Geek SDK进展2025Q2

Ardupilot开源无人机之Geek SDK进展2025Q2 1. 源由2. 内容汇总2.1 【jetson-fpv】“Caution - Hot surface. Dont touch.”2.2 【jetson-fpv】1080P/720P显示设备配置 3. 遗留问题3.1 高优先级3.1.1 【jetson-fpv】1080P60FPS AI分析视频卡顿&#xff0c;丢包3.1.2 【jetson-fp…...

深入理解K8s与Docker的关系:容器化技术的双雄

友情提示&#xff1a;本文内容由银河易创&#xff08;https://ai.eaigx.com&#xff09;AI创作平台gpt-4-turbo模型生成&#xff0c;仅供参考。 在现代云计算及微服务架构的发展中&#xff0c;Docker与Kubernetes&#xff08;K8s&#xff09;作为两大核心技术&#xff0c;被广泛…...

QT高效文件I/O编程--实用指南与最佳实践

概述 在软件开发过程中,文件输入输出(I/O)操作是数据持久化和交换的核心部分。无论是简单的日志记录还是复杂的数据集处理,高效的文件I/O操作对于应用的整体性能至关重要 最佳实践 一、选择合适的文件模式 正确选择文件打开模式是确保操作意图明确且安全的第一步。不同…...

QT记事本

记事本应用程序提供了基本的文本编辑功能&#xff0c;支持文件的新建、打开、保存和另存为操作&#xff0c;同时具备修改提示和关闭窗口时的保存确认功能。使用 UTF - 8 编码确保了对多语言文本的支持。 1. 项目整体结构 main.cpp&#xff1a;程序的入口点&#xff0c;负责初…...

【leetcode hot 100 84】柱状图中最大的矩形

解法一&#xff1a;单调栈 class Solution {public int largestRectangleArea(int[] heights) {int len heights.length;int area 0;// 先做一些特殊判断if(len0){return 0;}if(len1){return heights[0];}// 进入栈后发现后面更短&#xff0c;可以得到当前这个能勾勒的面积 …...

Spring----ioc

1.Spring 是什么&#xff1f; 通过前⾯的学习, 我们知道了Spring是⼀个开源框架, 他让我们的开发更加简单. 他⽀持⼴泛的应⽤场景, 有着活跃⽽庞⼤的社区, 这也是Spring能够⻓久不衰的原因. 但是这个概念相对来说, 还是⽐较抽象. 我们⽤⼀句更具体的话来概括Spring, 那就…...

C++——重载

目录 一、函数重载 基本概念 函数重载的条件 编程示例 代码讲解 函数重载的注意事项 二、运算符重载 什么是运算符重载&#xff1f; 运算符重载的实质是什么&#xff1f; 运算符重载函数的写法 运算符重载的基本语法 可重载的运算符列表 基本原则 编程示例 代码解…...

答疑解惑:EMC VMAX3 MMCS控制台不定期重启原因分析

今天有个朋友咨询他们有一台EMC的VMAX100k设备&#xff0c;其中MMCS2的管理控制台定期重启&#xff0c;但始终无法找到重启原因&#xff0c;稍微花了点时间&#xff0c;帮客户看了下。先说结论&#xff0c;MMCS2确实不定期发生重启&#xff0c;每次reboot都是一样的message信息…...

单例模式(Singleton Pattern)

单例模式&#xff08;Singleton Pattern&#xff09; 任务管理器可以作为一个全局的任务配置管理类&#xff0c;使用单例模式保证全局只有一个实例。这样你可以避免在应用程序中创建多个任务管理对象&#xff0c;保持配置参数的统一。 示例&#xff1a; class TaskManager { …...

树莓派超全系列文档--(8)RaspberryOS实用程序

RaspberryOS实用程序 实用程序kmsprintvclogvcgencmdvcosversionget_throttledmeasure_tempmeasure_clock [clock]measure_volts [block]otp_dumpget_config [configuration item|int|str]get_mem typecodec_enabled [type]mem_oommem_reloc_statsread_ring_osc 文章来源&#…...

Rust 与 FFmpeg 实现视频水印添加:技术解析与应用实践

引言 在短视频、直播、影视制作等领域&#xff0c;视频水印是一种常见的工具&#xff0c;用于保护版权、提升品牌辨识度或满足合规性要求。然而&#xff0c;开发者在实现水印添加时往往面临以下挑战&#xff1a; 手动处理效率低&#xff1a;使用图像编辑软件&#xff08;如 P…...

绿联NAS安装内网穿透实现无公网IP也能用手机平板远程访问经验分享

文章目录 前言1. 开启ssh服务2. ssh连接3. 安装cpolar内网穿透4. 配置绿联NAS公网地址 前言 大家好&#xff0c;今天给大家带来一个超级炫酷的技能——如何在绿联NAS上快速安装cpolar内网穿透工具。想象一下&#xff0c;即使没有公网IP&#xff0c;你也能随时随地远程访问自己…...

如何在 React 项目中使用React.lazy和Suspense实现组件的懒加载?

大白话如何在 React 项目中使用React.lazy和Suspense实现组件的懒加载&#xff1f; 在 React 项目里&#xff0c;有时候组件功能多、体积大&#xff0c;要是一次性把所有组件都加载进来&#xff0c;网页加载速度就会变慢。而 React 提供了 React.lazy 和 Suspense 这两个好东西…...

虫洞数观系列一 | 豆瓣电影TOP250数据采集与MySQL存储实战

目录 系列文章 1. 引言 2 技术栈Request 2.1请求头headers 2.2查找定位信息 2.3处理网页html结构化数据 2.4每页url规律 2.5逐条查找所需信息 2.6完整代码 3 数据存储至mysql 3.1新建数据库 3.2编写数据库写入py文件 3.2.1构建1个执行sql语句的函数 3.2.2构造一个…...

模型 阿米巴模式

系列文章分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。小团队独立经营&#xff0c;企业活力无限。 1 阿米巴模式的应用 1.1 日航重生&#xff08;航空业成功案例&#xff09; 应用领域 航空运输业破产重组与组织激活 案例名称 日本航空&#xff08;JAL&…...

针对stm32F103C8t6芯片调节USB串口的经验

1、首先这是自己手搓的板子,对于之前一直没有了解过USB这方面,则这个针对USB部分没有设计上拉电阻,造成不管怎么调节PC端都没有反应。 图一 这个没有添加1.5K电阻 这个D+位置应该再接一个1.5KR的电阻如图2所示 图2 这样调节的话PC端就可以识别到USB串口,但是这是串口还是会…...

JVM详解(包括JVM内存模型与GC垃圾回收)

&#x1f4d6;前言&#xff1a; 学会使用Java对于一个程序员是远远不够的。Java语法的掌握只是一部分&#xff0c;另一部分就是需要掌握Java内部的工作原理&#xff0c;从编译到运行&#xff0c;到底是谁在帮我们完成工作的&#xff1f; 接下来着重对Java虚拟机&#xff0c;也就…...

解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《深度探秘&#xff1a;AI界的007》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是Docker 2、什么是Ollama 二、准备工作 1、操…...

【Linux网络】——Socket网络编程

前言 在当今数字化的时代&#xff0c;网络通信已经成为计算机领域不可或缺的一部分。无论是日常的网页浏览、社交媒体交互&#xff0c;还是大规模的企业级数据传输&#xff0c;都离不开高效可靠的网络通信。而在Linux操作系统中&#xff0c;Socket网络编程是实现各种网络应用的…...

基于javaweb的SpringBoot雪具商城系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...

Android 简化图片加载与显示——使用Coil和Kotlin封装高效工具类

为了简化使用Coil加载网络图片和GIF的过程&#xff0c;我们可以封装一个工具类。这个工具类将包括初始化ImageLoader的方法、加载图片到ImageView的方法&#xff0c;以及可能的其他便捷方法&#xff0c;如加载圆形图片、设置占位图等。下面是一个示例&#xff1a; 首先&#x…...

Flink watermark的时间字段有空值,建表的时候,如何处理

在 Flink 中处理时间字段存在空值时&#xff0c;需通过 表定义阶段的特殊处理 和 Watermark 生成策略调整 来避免因空值导致的窗口计算异常或任务失败。以下是具体解决方案及实现方法&#xff1a; 1. 空值处理核心策略 1.1 查询时&#xff0c;过滤空值数据&#xff08;推荐&am…...

关于matlab和python谁快的问题

关于matlab和python谁快的问题&#xff0c;python比matlab在乘法上快10倍&#xff0c;指数计算快4倍&#xff0c;加减运算持平&#xff0c;略慢于matlab。或许matlab只适合求解特征值。 import torch import timen 50000 # 矩阵规模 M torch.rand(n, 31)start_time time.t…...

【DevOps】DevOps and CI/CD Pipelines

DevOps 是一种将开发与运维实践相结合的模式&#xff0c;旨在缩短软件开发周期并交付高质量软件。 DevOps 是什么&#xff1f; 开发团队与运维团队之间的协作 • 持续集成与持续交付&#xff08;CI/CD&#xff09; • 流程自动化 • 基础设施即代码&#xff08;IaC&#xff09;…...

ROS--IMU数据包

IMU惯性测量单元 一&#xff1a;IMU二&#xff1a;ROS中三&#xff1a;IMU数据包三&#xff1a;总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一&#xff1a;IMU IMU&#xff08;Inertial Measurement Unit&#xff0c;惯性测量单元&#xff09…...

【机器学习】手撕封装PCA——将高维数据映射到低维数据的过程

PCA将高维数据映射到低维数据的过程 一、摘要二、PCA的降维思路三、PCA代码实现降维过程3.1 PCA类的实现与封装3.2 PCA类的使用示例 四、PCA的恢复过程 一、摘要 本文详细介绍了主成分分析法&#xff08;PCA&#xff09;在高维数据降维中的应用。首先&#xff0c;阐述了PCA的基…...

LangChain开发(七)自定义输出格式(JSON/XML/YAML)

文章目录 JSON结构输出未使用PydanticPydantic流式处理 XML结构输出xml输出指定字段 YAML输出源码地址参考资料 JSON结构输出 虽然一些模型提供商支持内置的方法返回结构化输出&#xff0c;但并非所有都支持。我们可以使用输出解析器来帮助用户通过指示指定任意的JSON模型&…...

RustDesk部署到linux(自建服务器)

简介 ‌RustDesk‌是一款开源的远程桌面软件&#xff0c;由中国开发者开发&#xff0c;使用Rust编程语言构建。它支持跨平台运行&#xff0c;可以在Windows、macOS、Linux、iOS、Android和Web等多个平台上使用。RustDesk的主要功能包括远程桌面访问、文件传输、文本聊天等&…...

分布式锁,redisson,redis

目录 什么是分布式锁分布式锁解决什么问题分布式锁的特点使用分布式锁的场景怎么使用分布式锁1. 添加依赖2. 配置 Redisson 客户端3. 使用 Redisson 实现分布式锁 什么是分布式锁 分布式锁是一种锁机制&#xff0c;用于在分布式环境下&#xff0c;解决多个线程并发访问同一共享…...

linux常用指令(9)

加油同志们,我们离胜利不远了,再有两天我们就可以了解完linux的一些基本常用指令了,到时我们便可以进入一些shell脚本语法了,那么话不多说,来看. 1.more指令 功能描述&#xff1a;more指令是一个基于vi编辑器的文本过滤器,它以全屏幕的方式按页显示文本文件的内容. 基本语法…...

深入解析 JVM 内存区域及核心概念

深入解析 JVM 内存区域及核心概念 Java 虚拟机&#xff08;JVM&#xff09;内部划分了多个内存区域&#xff0c;每个区域存储不同类型的数据并承担不同的职责。本文将详细介绍以下内容&#xff1a; 程序计数器&#xff1a;记录当前线程正在执行的字节码指令及其“行号”信息&a…...

字节跳动春招研发部笔试题解

字节跳动春招研发部笔试题 1.万万没想到之聪明的编辑 我叫王大锤&#xff0c;是一家出版社的编辑。我负责校对投稿来的英文稿件&#xff0c;这份工作非常烦人&#xff0c;因为每天都要去修正无数的拼写错误。但是&#xff0c;优秀的人总能在平凡的工作中发现真理。我发现一个发…...

java对象模型

java对象自身的存储模型JVM会给这个类创建一个instanceKlass&#xff0c;保存在方法区&#xff0c;用来在JVM层表示该Java类。 a类。当我们在Java代码中&#xff0c;使用new创建一个对象的时候&#xff0c;JVM会在栈中给对象赋值&#xff0c;会在堆中创建一个instanceOopDesc对…...

深入理解指针(3)(C语言版)

文章目录 前言 一、字符指针变量二、数组指针变量2.1 数组指针变量是什么2.2 数组指针变量怎么初始化2.2.1 静态初始化2.2.2 动态初始化 三、二维数组传参的本质四、函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用4.3 typedef关键字4.4拓展 五、函数指针数组六、转…...