泛型<E>

news2024/11/25 2:22:48

泛型

案例引出泛型
按要求写出代码:
在ArrayList中添加3个Dog对象,Dog对象有name和age两个属性,且输出name和age

public class test1 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Dog(10,"小黑"));
        list.add(new Dog(3,"小白"));
        list.add(new Dog(7,"小黄"));
        for (Object o: list) {
            Dog d = (Dog) o;
            System.out.println(d);
        }
    }
}
class Dog{
    public Dog(int age, String name) {
        this.age = age;
        this.name = name;
    }

    int age;
    String name;

    @Override
    public String toString() {
        return "Dog{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

以上是正常情况,那么在实际开发中很多时候可能不是那么的顺利,比如程序员不小心放了只猫Cat进去,那么运行到增强for的时候就会报类型转换异常。这样的话就会引出两个问题

1:无法对加入到集合的数据进行约束,不安全
2:遍历的时候,需要进行类型转换,如果数据量很大,就会拉低效率

泛型的定义

泛型是 Java SE5 出现的新特性,泛型的本质是类型参数化或参数化类型,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型。

通俗的说:一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,得借助Object,但是如果要用到方法还得向下转型,这种刻板的限制对代码的束缚就会很大。

泛型的作用:把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型,可以有效避免ClassCastException

使用泛型解决开头问题

泛型的简单使用,用符号表示在集合的后面,可以限制加入集合的元素类型只能是x类型或是它的子类
ArrayList < Dog > list = new ArrayList< Dog >();

public class test1 {
    public static void main(String[] args) {
        ArrayList<Dog> list = new ArrayList<Dog>();
        list.add(new Dog(10,"小黑"));
        list.add(new Dog(3,"小白"));
        list.add(new Dog(7,"小黄"));
       // list.add(new Cat());
        for (Dog d:list) {
            System.out.println(d);
        }
    }
}

这样就可以约束加入集合的类型,且也不用向下转型了。解决了开头的两个问题
在这里插入图片描述

了解泛型

泛(广泛)型(类型),从名字就可以大概知道,泛型表示广泛的类型的意思,有点类似于Object,有点包容万象的意思,只不过泛型不用向下转型。
泛型的声明一般用一个标识表示类中的某个属性,方法返回值或者是参数类型。
一般都会使用< E >来表示泛型(也可以是< C >或者其他字母,但是不能是类名,否则就是直接指定是哪个类了),泛型并不指某个固定的类型,它可以是任何类型
思想解释:
例如:int a = 1,此时a就是1,
a = 2,此时a又变成了2.

泛型就是把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型

代码说明:

public class test2 {
        public static void main(String[] args) {
                Person<String> p = new Person<String>("name");
                System.out.println(p.s.getClass());
                Person<Integer> i = new Person<Integer>(2);
                System.out.println(i.s.getClass());
        }
}
class Person<E>{
        E s;

        public Person(E s) {
                this.s = s;
        }

        public E f(){
                return s;
        }
}

运行结果:
class java.lang.String
class java.lang.Integer
可以看到,的具体类型是定义的时候决定的,比较类似于形参的思想。代表任何类型,在具体定义和使用时才决定具体是什么类型。同样的一旦确定了是什么类型,那就代表着是那个类型,就不能再当作是任何类型来使用了。

泛型的语法

泛型的声明
interfece接口{}和class类<K,V>{}
其中T,K,V不代表值,而是表示类型,任何字母都可以,常用T表示,是Type的缩写

泛型的实例化
List< String > list = new ArrayList< String >();
在接口和类名后面指定泛型的类型,例如上面就表示,此集合只能加入String类型的
iterator< Student >iterator = set.iterator();
表示迭代器接收的类型只能是Student

泛型的实际使用

创建3个学生对象,分别放到HashMap和HashSet中,HashSet只放学生对象即可
HashMap放String name和学生对象,使用两种方式遍历

public class test3 {
    public static void main(String[] args) {
        HashSet<Student> hashSet = new HashSet<Student>();
        Student s1 = new Student("小明",11);
        Student s2 = new Student("小红",12);
        Student s3 = new Student("小王",18);
        hashSet.add(s1);
        hashSet.add(s2);
        hashSet.add(s3);
        HashMap<String,Student> hashMap = new HashMap<String,Student>();
        hashMap.put(s1.name,s1);
        hashMap.put(s2.name,s2);
        hashMap.put(s3.name,s3);
        Iterator<Student> iterator = hashSet.iterator();
        while (iterator.hasNext()) {
            Student next =  iterator.next();
            System.out.println(next);
        }
        Set<Map.Entry<String,Student>>set = hashMap.entrySet();
        Iterator<Map.Entry<String,Student>> iterator2 = set.iterator();
        while (iterator2.hasNext()) {
            Map.Entry<String, Student> next =  iterator2.next();
            System.out.println(next.getKey()+"--"+next.getValue());
        }
        
    }
}
class Student{
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

根据实际定义泛型的类型去debug替换方法中的<K,V>即可搞明白。

泛型的使用注意事项

  1. 在指定泛型类型的时候只能放引用类型,不能放基本类型。
    例如 Person< Integer > = Person(),这是可以的, Person< int> = Person(),,这是错误的

  2. 在指定泛型类型后,传入的类型只能是指定的类型,或者是他的子类型

  3. 泛型使用格式:
    Person< Integer > = Person< Integer >();
    Person< Integer > = Person<>();
    以上两者都是可以的,但是建议第二种写法,编译器会自动识别右边也是同样的类型

  4. 如果定义类的时候写了泛型,但是实例化的时候没有添加泛型,那么就等同于指定了< Object >
    例如:

//mian方法
Pig p = new Pig();

class Pig< E >{
}

Pig p = new Pig();就等于Pig p< Object > = new Pig< Object >();

泛型小练习

定义Employee类
1)该类包含,private成员变量name,sal,birthday,其中birthday为MyDate类的对象
2)为每个属性定义get,set方法
3)重写toString方法输出三个变量
4)MyDate类包含private成员变量month,day,year并且为每个属性定义get,set方法
5)创建Employee类的3个对象,并且将这三个对象放入ArrayList集合中(使用泛型定义),对集合中的元素进行排序,遍历输出
排序方式:调用ArrayList的sort方法,传入Comparator对象(使用泛型),按照name排序,如果name相同,则按生日的日期先后排序

public class test {
    public static void main(String[] args) {
        ArrayList<Employee> arrayList = new ArrayList();
        Employee e = new Employee();
        arrayList.add(new Employee("艾伦",13000,e.new MyDate(5,6,2000)));
        arrayList.add(new Employee("黄戈",7000,e.new MyDate(7,3,2008)));
        arrayList.add(new Employee("六子",23000,e.new MyDate(25,7,2000)));
        arrayList.sort(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                if (o1.getName().length()!=o2.getName().length()){
                    return o1.getName().length()-o2.getName().length();
                }
                return o1.getBirthday().compareTo(o2.getBirthday());
            }
        });
        System.out.println(arrayList);

    }
}
class Employee{
    private String name;
    private double sal;
    private MyDate birthday;

    public Employee() {

    }

    public Employee(String name, double sal, MyDate birthday) {
        this.name = name;
        this.sal = sal;
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return '\n' +"Employee{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", birthday=" + birthday +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    public MyDate getBirthday() {
        return birthday;
    }

    public void setBirthday(MyDate birthday) {
        this.birthday = birthday;
    }

    class MyDate implements Comparable<MyDate>{//内部类
        private int month;
        private int day;
        private int year;

        public MyDate(int day, int month, int year) {
            this.month = month;
            this.day = day;
            this.year = year;
        }

        @Override
        public int compareTo(MyDate o) {
            if (this.year!=o.getYear()){
                return year-o.getYear();
            }
            if (this.month!=o.getMonth()){
                return month-o.getMonth();
            }
            if (this.day!=o.getDay()){
                return day-o.getDay();
            }
            return 0;
        }

        @Override
        public String toString() {
            return year+"年"+month+"月"+day+"日";
        }

        public int getMonth() {
            return month;
        }

        public void setMonth(int month) {
            this.month = month;
        }

        public int getDay() {
            return day;
        }

        public void setDay(int day) {
            this.day = day;
        }

        public int getYear() {
            return year;
        }

        public void setYear(int year) {
            this.year = year;
        }
    }

}

自定义泛型

当在定义类或者接口时,在后面加上了泛型,那么这个类就是自定义泛型

自定义泛型类

基本语法
class 类名< T ,R,E …>{
成员
}

注意事项

  1. 普通成员可以使用泛型(属性,方法)
  2. 使用泛型定义的数组,不能初始化
  3. 静态方法中不能使用类的泛型
  4. 泛型类的类型,是在实例化时确定的
  5. 如果在实例化时没有指定泛型的类型,那么默认就是Object类型

自定义泛型类使用

public class test2 {
    Txt <String,Double,Integer> ttt = new Txt<>("你",23.4,2);
    //此时泛型就被指定了类型
}
class Txt <R,T,Y>{
    R r;//泛型定义属性
    T t;
    Y y;
    public Txt(R r, T t, Y y) {//构造方法使用类的泛型
        this.r = r;
        this.t = t;
        this.y = y;
    }
    public T MIN(R r){//方法使用类的泛型
        return t;
    }
    //public static R Dax(){T t}{}//静态方法不能使用类的泛型
    
}

为什么静态方法不能使用类的泛型

首先一个实例对象创建的过程是 类加载 ----- 静态方法加载 -------创建对象
而泛型的指定类型是在创建对象的时候才指定的,静态方法在此之前就已经加载了,所以它不知道你要的是什么类型,不知道如何加载了,所以不允许在静态方法中使用类的泛型

自定义泛型接口

基本语法
interface 接口名< T ,R >{
}
注意细节

  1. 接口中,静态成员 也不能使用泛型进行定义(与泛型类的原理是一样的),因为接口中的所有属性默认都是静态的,所以不知直接用泛型修饰属性
    在这里插入图片描述
  2. 泛型接口的类型,在继承接口或者实现接口时确定
public class test3 {
   
}
class Run implements AI{
   @Override
   public String mi() {
       return AI.super.mi();
   }
}
interface AI extends Iusb<String,Double>{}
interface Iusb <R,t>{
   default R mi(){
       return null;
   }
}
  1. 当继承接口或者实现接口时没有指定类型,那么默认就是指定了Object类型
public class test3 {

}
class Run implements AI{
    @Override
    public Object mi() {
        return AI.super.mi();
    }
}
interface AI extends Iusb{}//等同于interface AI extends Iusb<Object,Object>
interface Iusb <R,t>{
    default R mi(){
        return null;
    }
}

自定义泛型方法

基本语法
修饰符 < T , R… > 返回类型 方法名(参数列表){}

注意细节

  1. 泛型方法,可以定义在普通类中,也可以定义在泛型类中
class A <R,E>{
    public <F,G> void m(F f){}
}
class B{
    public <F,G> void m(F f){}
}
  1. 当泛型方法被调用时,泛型的类型才会确定
    就跟泛型类一样,定义泛型只是给个模板,具体是什么类型是在使用时确定的,如果是作为形参使用,那么在使用泛型方法时编译器就会自动确认是什么类型,如果是方法体中使用就得跟泛型类一样写出来是什么类型
public class test3 {
    public static void main(String[] args) {
        B b = new B();
        b.m("sr",12);
        System.out.println("==========");
        b.m(21.2,21.33f);
    }
}

class B{
    public <F,G> void m(F f,G g){
        System.out.println(f.getClass());
        System.out.println(g.getClass());
    }
}

结果:

class java.lang.String

class java.lang.Integer

==========
class java.lang.Double
class java.lang.Float

  1. 如果修饰符后面没有< T , R >那么这个方法就不是泛型方法,就算形参列表使用了类的泛型,也只是使用了泛型而已。
class B<E>{
    public void xx(E e){}//普通方法,非泛型方法
    public <F,G> void m(F f,G g){//泛型方法
        System.out.println(f.getClass());
        System.out.println(g.getClass());
    }
}

只有方法自己定义了泛型才是泛型方法

  1. 泛型方法不仅可以使用自己的泛型,也可以使用类的泛型
    泛型其实就是一个模板,为了给类或者方法使用的,类的泛型是提供给整个类使用的,方法的泛型是只提供给自己使用的。
    所以泛型方法可以使用类的泛型,而类却不能使用方法的泛型。
public class test3 {
    public static void main(String[] args) {
        B<Double> b = new B();//定义的时候指定
        b.m("String",2.11);
        B b2 = new B();
        b2.m("String","22");//使用方法的时候指定
    }
}
class B<E>{
    public <F,G> void m(F f,E e){//泛型方法
        System.out.println(f.getClass());
        System.out.println(e.getClass());
    }
}

class java.lang.String
class java.lang.Double
class java.lang.String
class java.lang.String

上面可以看到,如果泛型方法使用了类的泛型,而类的泛型在实例化时就定义了,那么泛型方法就只能传入对应的类型。
如果类的泛型没有在实例化的时候就定义那么默认就是Object的类型,传啥都可以

自定义泛型练习

  1. 分析下面代码是否正确,如果不正确,说明为什么
public class test3 {
    public static void main(String[] args) {
        Apple<String,Integer,Double>apple = new Apple<>();
        apple.fly(10);
        apple.fly(new Dog());
    }
}
class Apple<T,R,M>{
    public <E> void fly(E e){
        System.out.println(e.getClass().getSimpleName());
    }
    public void eat(U u){}
    public void eat(M m){}
}
class Dog{}

eat方法错误,因为没有定义泛型< U >
输出 Integer 和Dog

泛型的继承和通配符

泛型不具备继承性,例如下面的错误案例

ArrayList< Object > = new ArrayList< String >();
这样是不允许的。

但是可以通过特别的写法来实现与继承的搭配使用,这种写法就是通配符
通过前面的学习,我们知道泛型的主要用途是约束传入对象的类型
通配符有三种写法,对于约束的规则也有所不同

第一种:< ?> ,这种写法允许传入任何类型,上面的学习中就是使用这种
第二种:< ?extends A >.只允许传入A类或A的子类,限制了泛型的上限
第三种:< ?super A >,只允许传入A类或A的父类(不限于直接父类),限制了泛型的下限

举例说明:

public class test4 {
    public static void main(String[] args) {
        ArrayList<Object> l1 = new ArrayList<>();
        ArrayList<String> l2 = new ArrayList<>();
        ArrayList<AA> l3 = new ArrayList<>();
        ArrayList<CC> l4 = new ArrayList<>();
        
        //第一种<?>,可以传入任何类型,所以4个对象都能传入
        f(l1);
        f(l2);
        f(l3);
        f(l4);
        //第二种<? extends AA>.只能传入A类或者A的子类,所以l1和l2不能传入
        //f2(l1);
        //f2(l2);
        f2(l3);
        f2(l4);
        //第三种<? super AA>,只能传入A类或者A的父类,所以l2和l4不能传入
        f3(l1);
        //f3(l2);
        f3(l3);
        //f3(l4);
    }
    public static void f(List<?> c){}
    public static void f2(List<? extends AA> c){}
    public static void f3(List<? super AA> c){}
}
class AA{}
class BB extends AA{}
class CC extends BB{}

泛型作业

  1. 定义泛型类DAO< T >,在其中定义一个Map成员变量,Map的键为String 类型,值为T类型
    分别创建以下方法:
    public void save(String id ,T entity):保存T类型的对象到Map成员变量中
    public T get(String id):从map中获取id对应的对象
    public void update(String id,T entity):替换map中key为id的内容,改为entity对象
    public List< T >list():返回map中存放的所有T对象
    public void delete(String id):删除指定id对象

定义一个User类:private int id ,age。String name。
创建DAO类的对象,分别调用save,get,update,list,delete方法来操作User对象
使用JUnit单元测试类进行测试。(IDEA在需要单元测试的方法上添加注释@Test,引入JUnit,可以单独运行方法)
main方法一般是全部程序都在上面跑,这样不利于单独测试某一个功能,所以有了JUnit单元测试

public class HomeWork2 {
    public static void main(String[] args) {

    }
    @Test
    public void Test(){
        //创建DAO类的对象,分别调用save,get,update,list,delete方法来操作User对象
        //使用JUnit单元测试类进行测试。(IDEA在需要单元测试的方法上添加注释@Test,引入JUnit,可以单独运行方法)
        DAT<User> dat = new DAT<>();
        dat.save("01",new User(1,21,"李三"));
        dat.save("02",new User(2,25,"王三"));
        dat.save("03",new User(3,22,"赵三"));
        dat.get("03");
        dat.update("01",new User(1,24,"GHA"));
        dat.delete("02");
        System.out.println(dat.list());
    }
}
class DAT<T>{
    Map<String,T> map = new HashMap();;
    public void save(String id ,T entity){
        map.put(id, entity);
        //保存T类型的对象到Map成员变量中
    }
    public T get(String id){
        return map.get(id);
        //从map中获取id对应的对象
    }
    public void update(String id,T entity){
        //替换map中key为id的内容,将它的值改为entity
        map.put(id, entity);
    }
    public List< T > list(){
        List <T> list = new ArrayList<>();
        Set<String> set = map.keySet();
        for (String id:set) {
            list.add(get(id));
        }
        return list;
        //返回map中存放的所有T对象
    }
    public void delete(String id){
        map.remove(id);
        //删除指定id对象
    }
}
class User{
    private int id;
    private int age;
    private String name;

    public User(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/373715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python解题 - CSDN周赛第32期 - 运输石油(三维背包)

上期周赛因为最后一题出现bug&#xff0c;再加上都是经典的模板题&#xff0c;问哥就懒得写题解了。 本期也是有两道考过的题目&#xff0c;不过最后一题因为考到了背包问题的特殊类型&#xff0c;还是值得拿出来记个笔记。 第一题&#xff1a;传奇霸业 传奇霸业&#xff0c;是…

Unity高程图生成

序大概就是根据一个灰度图&#xff0c;生成一个地形。分两步来实现吧&#xff1b;首先&#xff0c;用随机数生成地形&#xff1b;然后&#xff0c;根据灰度图生成地形。小白&#xff0c;没啥基础&#xff0c;所以只能慢慢来。参考&#xff1a;【萌新图形学】地形网格生成入门 含…

基于stm32电梯管理系统设计

基于stm32电梯管理系统设计这里记录一下以前自己做的嵌入式课程设计&#xff0c;报告中的图片和文字太多了&#xff0c;全部一个一个把搬过来太麻烦了,需要完整文本和代码自行q我963160156&#xff0c;也可在微信公众号 *高级嵌入式软件* 里回复 *电梯* 查看完整版文章摘要关键…

Oracle Apex 21.2 安装过程

什么是 Oracle APEX&#xff1f; Oracle APEX 是广受欢迎的企业级低代码应用平台。借助该平台&#xff0c;您可以构建功能先进的可扩展安全企业应用&#xff0c;并在任何位置&#xff08;云或内部部署&#xff09;部署这些应用。 使用 APEX&#xff0c;开发人员可快速开发并部…

域组策略自动更新实验报告

域组策略自动更新实验报告 域组策略自动更新实验报告 作者: 高兴源 1要求、我公司为了完善员工的安全性和系统正常漏洞的维护&#xff0c;所以采用域组策略自动更新的方法来提高账户安全性&#xff0c;减少了用户的错误。 1.实验环境如下1台2008r2一台创建域&#xff0c;一台wi…

【云原生】k8s中Pod进阶资源限制与探针

一、Pod 进阶 1、资源限制 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 当为 Pod 中的容器指定了 request 资源时&#xff0c;调度器就使用该信息来决定将 Pod 调度到哪个节点上。当还…

嵌入式 STM32 步进电机驱动,干货满满,建议收藏

目录 步进电机 1、步进电机驱动原理 2、步进电机驱动 3、步进电机应用 1、第一步&#xff1a;初始化IO口 2、设置行进方式 四、源码 步进电机 步进电机被广泛应用于ATM机、喷绘机、刻字机、写真机、喷涂设备、医疗仪器及设备、计算机外设及海量存储设备、精密仪器、工业…

_improve-3

createElement过程 React.createElement()&#xff1a; 根据指定的第一个参数创建一个React元素 React.createElement(type,[props],[...children] )第一个参数是必填&#xff0c;传入的是似HTML标签名称&#xff0c;eg: ul, li第二个参数是选填&#xff0c;表示的是属性&#…

String、StringBuffer和StringBuilder的详解

目录 一、String讲解 1.String&#xff08;String字符串常量&#xff09; 2.String 拼接方式与性能的影响 二、StringBuffer 和 StringBuilder 讲解 1.StringBuffer 和 StringBuilder 使用场景:(StringBuffer、StringBuilder字符串变量) 2.StringBuffer的使用 3.StringB…

shell脚本常用命令

shell概述 shell是一个命令行解释器&#xff0c;它接收应用程序/用户命令&#xff0c;然后调用操作系统内核。 shell还是一个功能强大的编程语言&#xff0c;易编写、易调试、灵活性强。 shell解析器 查看系统自带的所有shell解析器 cat /etc/shells查看系统默认的shell解析…

超算中心、并行计算

现在超算中心已经迅速发展 合肥&#xff1a; 合肥先进中心 合肥曙光超算中心平台 合肥安徽大学超算中心 合肥中科大超算中心 合肥中科院超算中心 合肥大一点的公司都会有自己的集群&#xff0c; 超算中心又称为集群&#xff0c;一般集群是小型服务器组成&#xff0c;超…

EasyRecovery16免费的电脑的数据恢复工具

常见的数据恢复有两种方式&#xff0c;第一种方式是找别人恢复&#xff0c;按照市场价来说&#xff0c;数据恢复的价格每次在100-500之间&#xff0c;但这种方式容易使自己设备上的隐私资料泄露出去&#xff0c;不安全。 另一种方式则是自己学会数据恢复的方法&#xff0c;有问…

逻辑回归

逻辑回归 在分类问题中&#xff0c;要预测的变量y为离散值&#xff08;y0~1&#xff09;&#xff0c;逻辑回归模型的输出变量范围始终在 0 和 1 之间。 训练集为 {(x(1),y(1)),(x(2),y(2)),...,(x(m),y(m))}\{(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),...,(x^{(m)},y^{(m)})\} {…

地址,指针,指针变量是什么?他们的区别?符号(*)在不同位置的解释?

指针是C语言中的一个重要概念&#xff0c;也是C语言的一个重要特色&#xff1b;使用指针&#xff0c;可以使程序简洁、紧凑、高效。不掌握指针&#xff0c;就没有掌握C语言的精华。 目录 一、定义 1.1地址 1.2指针 1.3指针变量 1.4指针和指针变量的区别 二、使用指针变量…

C#关于HWindowControl实现一些便捷功能——(缩放与拖动图像)

C#关于HWindowControl实现一些便捷功能——&#xff08;缩放与拖动图像&#xff09;一、关于Hwindow窗体显示的part二、以鼠标为中心的缩放三、以鼠标拖动移动图片一、关于Hwindow窗体显示的part 首先 HWindowControl 控件的尺寸是固定的&#xff0c;当我们在这个固定的尺寸中…

C++类和对象:构造函数和析构函数

目录 一. 类的六个默认成员函数 二. 构造函数 2.1 什么是构造函数 2.2 编译器自动生成的默认构造函数 2.3 构造函数的特性总结 三. 析构函数 3.1 什么是析构函数 3.2 编译器自动生成的析构函数 3.3 析构函数的特性总结 一. 类的六个默认成员函数 对于任意一个C类&…

零基础如何入门网络安全(黑客)

我经常会看到这一类的问题&#xff1a; 学习XXX知识没效果&#xff1b;学习XXX技能没方向&#xff1b;学习XXX没办法入门&#xff1b; 给大家一个忠告&#xff0c;如果你完全没有基础的话&#xff0c;前期最好不要盲目去找资料学习&#xff0c;因为大部分人把资料收集好之后&a…

三天吃透Java虚拟机面试八股文

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

趣味数学题存疑待证1

原文出自&#xff1a;球面上随机 N 个点在同一个半球上的概率 要求任意N个点&#xff0c;全在同一个半球上的概率&#xff0c;我们需要构造使得分母为有限的样本集合&#xff0c;分子则为有N个点在同一半球的情况集 首先对任意N个点取其对称点使得可划分点为2N&#xff0c;在…

【数据库】第七章 数据库设计

第七章数据库设计 数据库设计概述 数据库设计的基本步骤 需求分析概念结构设计逻辑结构设计物理结构设计数据库实施数据库运行和维护 需求分析 收集需求&#xff0c;理解需求 收集各个角色的需求 概念数据库设计 建立概念模型 &#xff0c;E-R图/IDEF1x图 消除冲突&…