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

Java.lang包中的常用类 --8个包装类型、Math、Class

学习目标

  1. 掌握8个包装类型
  2. 掌握自动拆箱和自动装箱
  3. 了解Math
  4. 了解Object
  5. 了解Class

1.包装类

1.1. 什么是包装类

● 在Java中万事万物皆对象,但是基本数据类型的值就不是对象,那感觉就是这8个基本数据类型就很另类了;
● 因此为了让基本数据类型也具有对象的性质,JDK中定义了8个引用类型与前面所讲的8个基本数据类型相对应,而这8个引用类型都称之为包装类型;这8个类 都定义在java.lang包中,因此使用的时候也不需要显示导入;
包装类中定义了很多方法,静态或者实例的方法,丰富了对基本数据类型的操作;
● 之所以现在要讲包装类型,不仅是因为它们是常用类,而且 在后面要讲的集合的那一章里面,集合中是只能放对象而不能放基本数据类型的值的;因此必须要知道每个基本数据类型其所对应的包装类型;
● 这8个包装类的名称 除了 Integer Character名字不一样之外,其他都是 基本数据类型名称的首字母大写;
实际开发中, 需要从数据库中对接数据, 此时有可能对接null值, 且数据库中的数据存在数据类型区分, 所以无法存储null的基本类型不能应对该需求场景

● 简单对比基本数据类型与包装类型
● 基本数据类型 与包装类作用一致的。
● 为什么要提供与基本数据类型作用一致的包装类?
1. java是一门面向对象的语言。不能根据基本数据类型创建对象 不太符合面向对象的思想。
2. 丰富基本数据类型的操作 提供了8个包装类型。 包含一些属性/方法、创建对象、
3. 学习集合。是一个容器。存储引用数据类型的数据。

● 基本数据类型 VS 包装类型?
● 相同点: 代表具体的一个数据 作用是一致的。
● 不同点: 一个是类(属性/方法、创建对象) 一个是基本数据类型

基本数据类型默认值包装类型默认值
byte0Bytenull
short0Shortnull
int0Integernull
long0LLongnull
float0.0FFloatnull
double0.0DDoublenull
char\u0000Characternull
booleanfalseBooleannull
public static void method1() {
        byte by2 = 123;
        Byte by1;
        Short sh1;
        Integer in1;
        Long lo1;
        Float f1;
        Double d1;
        Character c1;
        Boolean b1;
    }

1.2. Integer

● 由于JDK存在8个包装类型,而且特征都是类似的。
● 因此我们在学习的时候以Integer以及Character为例,学习所有的包装类型。

1.2.1 层级

public final class Integer extends Number implements Comparable<Integer> {
    
}

1.2.2 常用构造

● 自从JDK9之后包装类的构造方法都不建议使用了,创建包装类对象的方式都直接使用字面量赋值。
● 所有的包装类型都是一样。

1.2.3 创建对象

private static void demo1() {
    //过时了  不建议使用
    Integer num1 = new Integer(100);
    //将string的数据转换成Integer对象的数据
    Integer num2 = new Integer("100");

    System.out.println(num1);
    System.out.println(num2);

    int num3 = 100;
    System.out.println(num3);

    Integer num4 = 100;
}

1.2.4 装箱与拆箱

jdk5+提供:为了简化双方的转换成本, 提供了自动封箱与自动拆箱

  • 自动装箱: 基本数据类型的数据转换成包装类型的对象 包装类.valueOf(基本数据类型 变量);
  • 自动拆箱: 包装类对象转换成基本类型的数据 包装类引用.xxxValue()
    总结一句话就是:两者使用上没差别 可以自动转;
	int n1 = 10;
    //自动封箱
    Integer i1 = n1;
    //自动拆箱
    int n2 = i1;

注意:

  1. 自动封箱与拆箱只能发生在相同类型之间
  2. 包装类型之间不存在大小关系, 其相互平级, 不能发生自动类型转换

1.2.5 整数缓存池

private static void demo3() {
        Integer num1 = new Integer("100");
        Integer num2 = new Integer(100);
        System.out.println(num1);
        System.out.println(num2);
        System.out.println("(num1==num2):" + (num1 == num2));//false

        //整数缓存池-----> 数组里面存储的整数 Integer (-128-127) 256
        Integer num3 = Integer.valueOf(100);
        //基本数据转包装类对象  自动装箱  底层: Integer.valueOf()
        System.out.println("(num1==num3):" + (num1 == num3));//false

        Integer num4 = 100;
        System.out.println("(num4==num3):" + (num4 == num3));//true  一块内存  new

        Integer num5 = 200;
        Integer num6 = 200;
        System.out.println("(num5==num6):" + (num5 == num6));//false

    }

● 整数缓存池。IntegerCache.cache[] -128-127之间的数字. 256个对象 new 256次
● 假如Integer num1 = 100; Integer num2 = 100; Integer num3 = 100; Integer num4 = 100; 其实内存中只有1个Integer对象。
优势: 提高资源的使用率 多次使用1个对象。避免内存的过渡浪费

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer[] cache;//存储都是Integer对象

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

哪些包装类中具备整数缓存池思想?

  1. Integer-----> IntegerCache.cache Integer[] cache -128-127
  2. Byte-----> ByteCache.cache Byte[] cache -128-127
  3. Short-----> ShortCache.cache Short[] cache -128-127
  4. Long-----> LongCache.cache Long[] cache -128-127
  5. Character----> CharacterCache.cache Character[] cache 0-127 128 ASCII

1.2.6 其它方法

public static void method2() {
//此赋值方式和String非常相似,注意in1,in2都是对象,都是引用
//in1和in2中所存储的依然的堆空间的某块内存的起始地址值
Integer in1 = 66;
Integer in2 = 999;
//静态的成员变量 代表此类型的表叔范围
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MAX_VALUE);
//静态方法parseInt() 把字符串转换为int类型 如果出现非数字的字符则会报异常 NumberFormatException 例如"abc";
int a1 = Integer.parseInt(“123”);
//静态方法valueOf() 功能是把字符串转换为其所对应的Integer对象 同样的如果出现非数字的字符则会报异常 NumberFormatException 例如"abc";
Integer in3 = Integer.valueOf(“123”);
// compareTo实例方法用于比较两个Integer对象的大小,返回值只有三种情况: 1表示第一个数大 0表示两个数相等
System.out.println("compareTo: " + in2.compareTo(1999));
System.out.println("parse: " + a1);
System.out.println(in3);
}

private static void demo6() {
    //Integer其他功能方法
    Integer num1 = 100;
    //1.Object.hashcode()获得对象的hash值
    System.out.println(num1.hashCode());//与对象的数据是一致的
    //2.与其他类型的转换
    float value = num1.floatValue();
    //3.运算
    System.out.println(Integer.sum(10, 20));
    System.out.println(Integer.max(10, 1));
    System.out.println(Integer.min(10, 1));
    System.out.println(Integer.toHexString(1000));
    //将10进制的整型的数据转换成无符号16进制的字符串

    //4.String与整型之间相互转换
    int num = 100;
    //int 转 String   +
    System.out.println(num + "");
    System.out.println(String.valueOf(num));

    Integer num2 = 200;
    System.out.println(num2.toString());
    System.out.println(num2 + "");
    System.out.println(String.valueOf(num2));
    System.out.println("-------------------------");
    //String转int
    String str = "1234";//转10进制
    /* Integer i = new Integer(str);
        System.out.println(Integer.valueOf(str));
        System.out.println(Integer.valueOf(str, 10));*/
    //将指定的字符串数据 转换成指定进制的数值
    // 2    0   1
    // 8    0-7
    // 10   0-9
    // 16   0-F
    // 36   0-Z
    int anInt = Integer.parseInt(str);
    System.out.println(anInt);

    System.out.println(Character.MIN_RADIX);
    System.out.println(Character.MAX_RADIX);

}

1.3 Character

了解里面常用的方法即可。

public static void method6() {
    // 静态方法
    System.out.println(Character.toUpperCase('a'));
    System.out.println(Character.toLowerCase('A'));
    Character character = 'a';
    Character character1 = Character.valueOf('a');
    char[] chars = {'2', 'a', 'A'};
    for (int i = 0; i < chars.length; i++) {
        System.out.print(chars[i]);
        System.out.println(Character.isDigit(chars[i]) ? "是数字字符" : "不是数字字符");
        System.out.println(Character.isLetter(chars[i]) ? " isLetter " : " not letter");
        System.out.println(Character.isUpperCase(chars[i]) ? " isUpper " : " not Upper");
        System.out.println(Character.isLowerCase(chars[i]) ? " isLower " : " not lower");
    }
    int digit(char ch, int radix) 将字符转换成指定进制的数字
    int result = Character.digit('Z', 36);
    System.out.println(result);//-1
}

1.4 值不可变性

● 8个包装类数据是不可变的,其对象也都是不可变的对象;
● 原因都是其内部用来存储值的成员变量都是使用final修饰的,一旦赋值不可改变。

 /**
     * 2,Integer 包装类型都是 是不可变的对象 每次重新赋值 都会有新的对象
     */
    public static void method3() {
        //如下代码 是有2个字符串对象 而str只是个引用而已,引用中存储的是地址
//        String str = "abc";
//        str="java";
        //同样的in1也是引用类型 所有in1中存储的也是地址。下面的代码中有两个Integer对象;
        Integer in1 = 127;
        in1 = 128;
    }

包装类内部用于存储值的成员变量源码

 /**
     * The value of the {@code Integer}.
     *
     * @serial
     */
    private final int value;

1.5 进制与位运算

程序中使用的进制的表示

 /**
     * 进制  
     * 二进制(逢2进1) 以0b/0B 打头
     * 八进制(逢8进1) 以数字0打头
     * 十进制(逢10进1)
     * 十六进制(逢16进1 A-10 b-11 c-12 d-13 e-14  f-15)
     *        0x或者0X 16进制的1位相当于二进制的4位
     */
    public static void method7() {
        int a = 012; // 0000 1010
        System.out.println("八进制 0: " + a);
        int b = 0Xaf; // 15+10*16
        System.out.println("16进制: " + b);
        int c = 0b10101111;
        System.out.println("2进制: " + c);
    }

位运算: 左移与右移

/**
     * << 左移动相当于乘2的指数值    >>向右移动 相当于除2的指数值
     */
    public static void method8() {
        //  0011  1100
        System.out.println(3 << 2); // 3*2^2
        // 1010 0010
        System.out.println(10 >> 2); // 10/2^2
    }

逻辑符号用于数值运算
● &表示两边都为1 结果才是1
● |表示两边只要有一个是1 结果就是1

 	/**
     * & |
     */
    public static void method9() {
        /**
         *  1111
         *  1010   &表示上下都为1才是1  |是只要有一个为1就是1
         *  ------------
         *  1010
         */
        System.out.println(15 & 10);
        System.out.println(15 | 0);
    }

1.6 使用场景

//使用场景
//在以后类中  属性/形参/返回值类型  建议使用包装类型维护
public class UserInfo {

    //private int  id;//0
    //private Integer id;//null

    //public double zengZhangLv;
    //public Double zengZhangLv;//增长率 null%
    //增长率 0.0% 由于某些原因忘记赋值或者程序报错,对于基本类型有默认值,比如0.0 
    //在这种情况下  可能会认为0.0% 也是ok的数据。
    

    public Integer demo(int num){
        //局部变量  建议使用基本数据类型
        //形参与返回值类型建议使用包装类型  可以结合null值进行提前预判  规避一些不正常的现象产生。
        //如果真的不想用  其实影响也不是很大。我们了解这种情况即可。
        return null;
    }
}

2.Math

● Math单词表示数学。因此Math类内部提供的都是和数学运算相关的方法;
● Math类内部所有的方法都是静态方法,都是功能性方法;

 /**
     * Math类的常用方法
     * 数学运算相关方法
     */
    public static void method1() {
        System.out.println("绝对值:" + Math.abs(-32));
        System.out.println(Math.PI);
        System.out.println("次方: " + Math.pow(12.5, 2));
        System.out.println("开根号: " + Math.sqrt(16));
        System.out.println("max: " + Math.max(16, 10));
        System.out.println("min: " + Math.min(16, 10));
        System.out.println("[0,1) 浮点数: " + Math.random());
        // 四舍五入值
        System.out.println(Math.round(5.5));
        // ceil 向上取整 取最小
        System.out.println(Math.ceil(5.3));
        // floor 向下取整 取最大
        System.out.println(Math.floor(5.3));
         //+ - *
        System.out.println(Math.addExact(10, 20));
        System.out.println(Math.subtractExact(10, 20));
        System.out.println(Math.multiplyExact(10, 20));
    }

3.Object

超级父类。需要了解Object类中的每个方法。

3.1 常用方法

方法作用
String toString()返回对象的字符串表示形式。
protected Object clone();创建并返回此对象的副本
boolean equals(Object obj)比较2个对象是否相等
Class<?> getClass()返回此 Object的运行时类。获得当前正在运行的类或者接口的class类对象。
int hashCode()返回对象的哈希码值
void notify()唤醒正在此对象监视器上等待的单个线程
void notifyAll()唤醒等待此对象监视器的所有线程。
void wait()当前线程等待
void wait(long timeoutMillis)时间内等待
void wait(long timeoutMillis, int nanos)

3.2 toString

● 面向对象本质: 使用对象封装数据 使用类管理代码
● 打印输出对象,就是想看到属性的数据。底层默认执行toString的方法,打印输出的16进制的hash值

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class UserInfo /*extends Object*/{

    private Integer id;
    private String name;
    private Integer age;

//    @Override
//    public String toString() {
//        return "UserInfo{" +
//                "id=" + id +
//                ", name='" + name + '\'' +
//                ", age=" + age +
//                '}';
//    }
}
public static void main(String[] args) {

    UserInfo userInfo1 = new UserInfo(1,"张三",18);
    UserInfo userInfo2 = new UserInfo(1,"张三",18);

    //打印输出引用类型对象 底层默认Object.toString()
    System.out.println(userInfo1.toString());
    System.out.println(userInfo2);
}

3.3 equals+hashcode

为什么重写equals+hashcode?

在正常生活中 我们会认为2个对象 是一个对象。 true
比较2个对象是否一致/相等
1.比较运算符: == 内存地址值
2.比较对象: equals+hashcode

  • 在jvm规范: 2个对象的hashcode不同 这2个对象就是不等的。
  • 2个对象的hashcode相同 不能直接认为2个对象相同的 hash算法有弊端。hash会经常出现碰撞。
  • 2个对象equals 结果true 这2个对象的hash必须相同。
  • jvm硬性规定: 重写equals 也必须重写hashcode。equals+hashcode规则一致的。

需求: 比较2个对象是否一致/相等

public boolean equals(Object obj) {
    return (this == obj);
}
 public native int hashCode();
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString    
public class UserInfo {

    private Integer id;
    private String name;
    private Integer age;
}
public static void main(String[] args) {

        UserInfo userInfo1 = new UserInfo(1, "张三", 18);
        UserInfo userInfo2 = new UserInfo(2, "张三", 20);

        //打印输出引用类型对象 底层默认Object.toString()
        System.out.println(userInfo1.toString());
        System.out.println(userInfo2);
       

        //System.out.println("(userInfo1==userInfo2):" + (userInfo1 == userInfo2));
        System.out.println("(userInfo1.equals(userInfo2)):" + userInfo1.equals(userInfo2));
        int code1 = userInfo1.hashCode();
        int code2 = userInfo2.hashCode();
        System.out.println(code1);
        System.out.println(code2);

        String s1 = "Ma";
        String s2 = "NB";
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString
//@EqualsAndHashCode //类中所有的属性都参与
public class UserInfo /*extends Object*/ {

    private Integer id;
    private String name;
    private Integer age;

    //2个对象相等的规则:  id  name  age 都相同的时候
    @Override
    public boolean equals(Object obj) {
        //this  obj
        if (obj == null) return false;
        if (!(obj instanceof UserInfo)) return false;
        UserInfo userInfo = (UserInfo) obj;

        return
                Objects.equals(name, userInfo.name)
        ;
    }

    //重写父类的hashcode

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

3.4 clone

克隆对象。属于创建对象的一种方式

Object里面的clone()方法

protected native Object clone() throws CloneNotSupportedException;
@Setter
@Getter
@Accessors(fluent = true)
@ToString
public class GirlFriend extends Object implements Cloneable {

    //Cloneable是一个标记接口。类实现Cloneable接口 代表这个类对象可以被克隆的。
    private Integer id;
    private String name;
    private int age;
    private String[] hobby;

    //思考:复制的是数据还是内存地址值?
    //基本的数据类型: 数据
    //引用数据类型: 内存地址值

    

    //值的传递
    @Override
    public GirlFriend clone() {
        GirlFriend clone = null;
        try {
            clone = (GirlFriend) super.clone();
            //对属性执行遍历式克隆
            //clone.hobby(Arrays.copyOf(this.hobby,hobby.length));
            clone.hobby(this.hobby.clone());
        } catch (CloneNotSupportedException e) {
            System.out.println("类必须实现Cloneable接口");
            e.printStackTrace();
        }
        return clone;
    }

    public GirlFriend() {
        System.out.println("无参构造...........");
    }
}

浅克隆与深克隆

1.浅克隆(浅复制/copy)

  1. 是否真的可以克隆成功? 为什么会有CloneNotSupportedException?
  • 代码可能会报错。 类一定要实现Cloneable标记接口。
  1. 克隆的对象与源对象是否是同一个对象?
  • 不是同一个
  1. 克隆的对象是否执行了构造方法?
  • 没有执行构造方法。jvm底层调用C创建新的对象
  1. 克隆对象的属性的数据是否有值? 数据是否与原对象的属性的数据是一致的?
  • 有值 与源对象的数据是一致的。
    5.修改了一个对象的属性的数据 是否会影响另外一个对象的数据?
  • 在浅克隆的操作下 修改一个对象的数据 可能会影响另外一个对象的数据
  • 属性: 基本数据类型 没有任何影响 复制的是数据
  • 包装类型+String—> 值不可变 修改一个对象 值不变的
  • 其他的引用数据类型 数据就会发生改变 数组,自定义的类(浅克隆的弊端)
  1. 深克隆/序列化-----> 解决浅克隆的问题
  • 需求: 修改一个对象的数据 不要影响另外一个对象的数据、
  • 操作: 对象在哪里克隆的 就在那里修改
public static void main(String[] args) {

        String[] hobby = new String[]{"大提琴", "show", "sing"};
        GirlFriend girlFriend1 = new GirlFriend().id(1).name("欧阳娜娜").age(18).hobby(hobby);
        //克隆一个女友对象  Object.clone();
        //girlFriend1.clone
        //1.在其他类中  无法访问clone  protected
        //2.在父类clone方法中  返回值类Object----> GirlFriend
        //建议在子类中重写父类的方法

        GirlFriend cloneGirlFriend = girlFriend1.clone();

        System.out.println("girlFriend1:" + girlFriend1);
        System.out.println("cloneGirlFriend:" + cloneGirlFriend);
        cloneGirlFriend.id(2);
        cloneGirlFriend.name("欧阳娜娜2");
        cloneGirlFriend.age(20);
        cloneGirlFriend.hobby()[0] = "小提琴";
        System.out.println("---------------------------");

        System.out.println("girlFriend1:" + girlFriend1);
        System.out.println("cloneGirlFriend:" + cloneGirlFriend);


       

    }

● 克隆对单例是否有影响?

public class Cat implements Cloneable {

    private Cat() {
    }

    private final static Cat instance = new Cat();

    public static Cat getInstance() {
        return instance;
    }

    @Override
    public Cat clone() throws CloneNotSupportedException {
        return this;
    }
}
class Test{
    public static void main(String[] args) throws CloneNotSupportedException {
        /*for (int i = 0; i < 100; i++) {
            System.out.println(Cat.getInstance());
        }*/
        //克隆是否可以打破单例? 可以打破单例
        Cat cat1 = Cat.getInstance();
        Cat cloneCat = cat1.clone();
        System.out.println(cat1);
        System.out.println(cloneCat);

        System.out.println(cat1==cloneCat);
        //有且只有1个cat对象
    }
}

3.5 finalize

final  VS finally  VS finalize?
  1. final 修饰符
     类  变量  方法
  2. finally
     异常处理机制的关键字。  try....catch...finally  try...finally
     释放物理资源/释放监视器
     释放物理资源: jdk1.7+ 建议使用try...with....reources  省略finally代码块
         
  3.finalize
     是Object.finalize();  满足于GC回收无用引用关联的对象,释放内存。不需要手动调用。  目前方法过时了。

4.Class

● Class类代表当前程序中正在运行的类或者接口的Class类对象。
● Class类是反射机制的基础。
● 目前我们只先了解获得Class类对象的3种方式,与反射相关的技术点我们到后面学习。
● 在开发中,本质上下面3种方式,我们都可以使用。

private static void demo4() {

        //需求: 获得UserInfo.class在运行期间的Class类对象
        //1. Class getClass()  不推荐 与对象的耦合度太高了  不太建议
        UserInfo userInfo = new UserInfo();
        Class userInfoClass = userInfo.getClass();//userInfoClass就等价于获得UserInfo.class
        System.out.println(userInfoClass.toString());//class com.java .lang.UserInfo
        System.out.println(userInfoClass.getName());
        System.out.println(userInfoClass.getSimpleName());

        //2.使用静态属性  class  类型的名称.class   推荐使用的  在本项目内访问本项目内其他的类或者接口
        //任意一个类型里面 都有一个静态属性 class
        Class aClass = int.class;
        Class userInfoClass = UserInfo.class;
        Class cloneableClass = Cloneable.class;

        System.out.println(aClass);
        System.out.println(userInfoClass.toString());
        System.out.println(userInfoClass.getName());
        System.out.println(userInfoClass.getSimpleName());

        //3. Class.forName("类/接口的全限定名称");  类/接口的路径  包名+类名  com.java .lang.UserInfo
        //推荐  加载第3方类库资源里面的类或者接口 (jar)   
        try {
            Class aClass = Class.forName("com.java .lang.UserInfo");
            System.out.println(aClass.getName());
            System.out.println(aClass.getSimpleName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
}

相关文章:

  • 自动驾驶的等级划分
  • 逻辑架构与软件架构在PREEvision中的设计关系
  • 为Eclipse IDE安装插件IBM编程助手watsonx Code Assistant
  • 计算机创造的奇迹——C语言
  • 基于springboot+vue的新生报到管理系统
  • 探索YOLO技术:目标检测的高效解决方案
  • Webpack 的 require.context 和 Vite 的 import.meta.glob 的详细介绍和使用
  • 车载诊断数据库 --- AUTOSAR诊断文件DEXT简介
  • 区块链相关方法-PEST分析
  • USC安防平台之元数据检索
  • USC安防平台之地图临近资源列表
  • directx12 3d+vs2022游戏开发第六章 笔记十一
  • 核货宝助力连锁门店订货数字化转型升级
  • rust笔记7-生命周期显式标注
  • LLaMA中的微调方法
  • VSCode ssh远程连接内网服务器(不能上网的内网环境的Linux服务器)的终极解决方案
  • 【Python爬虫(50)】从0到1:打造分布式爬虫项目全攻略
  • mysql之Innodb数据页
  • Vue 2全屏滚动动画实战:结合fullpage-vue与animate.css打造炫酷H5页面
  • 学习路程一 从deepseek开始感兴趣
  • 《大风杀》导演张琪:为了不算计观众,拍了部不讨好的警匪片
  • 在古老的意大利科莫歌剧院,廖昌永唱响16首中国艺术歌曲
  • 第1现场 | 美国称将取消制裁,对叙利亚意味着什么
  • 第十二届警博会在京开幕:12个国家和地区835家企业参展
  • 首次采用“顶置主星+侧挂从星”布局,长二丁“1箭12星”发射成功
  • 金价大跌!足金饰品每克一夜便宜14元,涨势是否已终结?