Java 基础面试题——面向对象

news2024/11/17 11:55:36

目录

  • 1.面向对象和面向过程有什么区别?
  • 2.面向对象的有哪些特征?
  • 3.静态变量和实例变量有什么区别?
  • 4.Java 对象实例化顺序是怎样的?
  • 5.浅拷贝和深拷贝的区别是什么?
    • 5.1.浅拷贝
    • 5.2.深拷贝
    • 5.3.总结
  • 6.Java 中创建对象的方式有哪几种?
  • 7.重写和重载的区别是什么?
  • 8.Java 的四种引用方式分别是什么?
  • 9.构造方法有哪些特点?
  • 10.抽象类 (abstract class) 和接口 (interface) 有什么共同点和区别?
  • 11.什么是内部类?为什么需要使用内部类?
  • 12.匿名内部类可以继承类或实现接口吗?为什么?
  • 13.说说内存中的栈 (stack)、堆 (heap) 和静态存储区的用法。

1.面向对象和面向过程有什么区别?

(1)面向过程: 是分析解决问题的步骤,然后用函数把这些步骤一步一步地实现,然后在使用的时候一一调用则可。性能较高,所以单片机、嵌入式开发等一般采用面向过程开发。
(2)面向对象: 是把构成问题的事务分解成各个对象,而建立对象的目的也不是为了完成一个个步骤,而是为了描述某个事物在解决整个问题的过程中所发生的行为。面向对象有封装继承多态的特征,所以易维护、易复用、易扩展,可以设计出低耦合的系统。

2.面向对象的有哪些特征?

(1)抽象
抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

(2)继承
继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类或基类);得到继承信息的类被称为子类(或派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。

(3)封装
通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好,因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。

(4)多态
多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单地说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当 A 系统访问 B 系统提供的服务时,B 系统有多种提供服务的方式,但一切对 A 系统来说都是透明的(就像电动剃须刀是 A 系统,它的供电系统是 B 系统,B 系统可以使用电池供电或者用交流电, 甚至还有可能是太阳能,A 系统只会通过 B 类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种方式获得了动力)。
① 方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override) 实现的是运行时的多态性(也称为后绑定)。
② 运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1)方法重写。即子类继承父类并重写父类中已 有的或抽象的方法;2)对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

3.静态变量和实例变量有什么区别?

(1)静态变量是被 static 修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一份。静态变量可以实现让多个对象共享内存。在 Java 开发中,上下文类工具类中通常会有大量的静态成员。
(2)实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。

4.Java 对象实例化顺序是怎样的?

(1)类加载器实例化时进行的操作步骤:加载 -> 连接 -> 初始化

(2)实例化优先级顺序:父类 > 子类 , 静态代码块 > 非静态代码块 > 构造函数,具体按照如下顺序:
① 按照代码书写顺序加载父类静态变量父类静态代码块
② 按照代码书写顺序加载子类静态变量子类静态代码块
③ 父类非静态变量(父类实例成员变量);
④ 父类非静态代码块;
⑤ 父类构造函数;
⑥ 子类非静态变量(子类实例成员变量);
⑦ 子类非静态代码块;
⑧ 子类构造函数;

(3)举例说明如下:

class A {
    //静态代码块(只初始化一次)
    static {
        System.out.println("父类的静态代码块...");
    }
    
    //非静态代码块
    {
        System.out.println("父类的非静态代码块...");
    }
    
    //构造函数
    public A() {
        System.out.println("父类的构造函数...");
    }
}

class B extends A {
    //静态代码块(只初始化一次)
    static {
        System.out.println("子类的静态代码块...");
    }
    
    //非静态代码块
    {
        System.out.println("子类的非静态代码块...");
    }
    
    //构造函数
    public B() {
        System.out.println("子类的构造函数...");
    }
}

public class Solution {
    public static void main(String[] args) {
        A ab = new B();
        System.out.println("---------");
        ab = new B();
    }
}

上述代码的输出结果如下:

父类的静态代码块...
子类的静态代码块...
父类的非静态代码块...
父类的构造函数...
子类的非静态代码块...
子类的构造函数...
------------
父类的非静态代码块...
父类的构造函数...
子类的非静态代码块...
子类的构造函数...

5.浅拷贝和深拷贝的区别是什么?

5.1.浅拷贝

浅拷贝是创建一个新对象,该对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,那么拷贝的就是内存地址 。

public class Address {
    int id;
    String addressName;
    
    public int getId() {
        return id;
    }
    
    public String getAddressName() {
        return addressName;
    }
    
    public Address(int id, String addressName) {
        this.id = id;
        this.addressName = addressName;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public void setAddressName(String addressName) {
        this.addressName = addressName;
    }
    
    @Override
    public String toString() {
        return "Address{" +
                "id=" + id +
                ", addressName='" + addressName + '\'' +
                '}';
    }
}
public class Person implements Cloneable {
    private int id;
    private String name;
    private Address address;
    
    public String getName() {
        return name;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getId() {
        return id;
    }
    
    public Address getAddress() {
        return address;
    }
    
    public void setAddress(Address address) {
        this.address = address;
    }
    
    public Person(int id, String name, Address address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }
    
    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person(1, "小华", new Address(1, "北京"));
        //浅拷贝
        Person person2 = (Person) person1.clone();
        System.out.println("person1 == person2 的结果为:" + (person1 == person2));
    
        System.out.println("\n改变person1的属性值之前:");
        System.out.println("person1:" + person1);
        System.out.println("person2:" + person2);
        System.out.println("person1.getName() == person2.getName()的结果为:" + (person1.getName() == person2.getName()));
        System.out.println("person1.getAddress() == person2.getAddress()的结果为:" + (person1.getAddress() == person2.getAddress()));
        
        person1.setId(2);
        person1.setName("小明");
        person1.getAddress().setId(2);
        person1.getAddress().setAddressName("武汉");
    
        System.out.println("\n改变person1的属性值之后:");
        System.out.println("person1:" + person1);
        System.out.println("person2:" + person2);
        
        System.out.println("person1.getName() == person2.getName()的结果为:" + (person1.getName() == person2.getName()));
        System.out.println("person1.getAddress() == person2.getAddress()的结果为:" + (person1.getAddress() == person2.getAddress()));
    }
}

在这里插入图片描述

5.2.深拷贝

(1)深拷贝是将一个对象从内存中完整的拷贝一份出来,即从堆内存中开辟一个新的区域存放新对象。新对象与原对象不共享内存,修改新对象也不会影响原对象

(2)实现方式如下:
① 通过对象序列化实现深拷贝(推荐)
先将 Address 类和 Person 类实现 Serializable 接口,然后再修改Test.java中的代码即可。

public class Test {
    public static void main(String[] args) throws Exception {
        Person person1 = new Person(1,"小华",new Address(1,"北京"));
        
        //创建对象输出流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\testData\\a.txt"));
        //写对象
        oos.writeObject(person1);
        //释放资源
        oos.close();
        
        //创建对象输入流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\testData\\a.txt"));
        //读取对象(深拷贝)
        Person person2 = (Person) ois.readObject();
        //释放资源
        ois.close();
    
        System.out.println("person1 == person2 的结果为:" + (person1 == person2));
    
        System.out.println("\n改变person1的属性值之前:");
        System.out.println("person1:" + person1);
        System.out.println("person2:" + person2);
        System.out.println("person1.getName() == person2.getName()的结果为:" + (person1.getName() == person2.getName()));
        System.out.println("person1.getAddress() == person2.getAddress()的结果为:" + (person1.getAddress() == person2.getAddress()));
    
        person1.setId(2);
        person1.setName("小明");
        person1.getAddress().setId(2);
        person1.getAddress().setAddressName("武汉");
    
        System.out.println("\n改变person1的属性值之后:");
        System.out.println("person1:" + person1);
        System.out.println("person2:" + person2);
    
        System.out.println("person1.getName() == person2.getName()的结果为:" + (person1.getName() == person2.getName()));
        System.out.println("person1.getAddress() == person2.getAddress()的结果为:" + (person1.getAddress() == person2.getAddress()));
    }
}

在这里插入图片描述

② 重写Person 类中的 clone() 方法来实现深拷贝

public class Address implements Cloneable {

   	//...
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }
    
    //...
}
public class Person implements Cloneable {
    
    //...
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        Person person = null;
        person = (Person)super.clone();
        //对引用数据类型单独处理
        person.name = new String(name);
        person.address = (Address)address.clone();
        return person;
    }
    
    //...
}

5.3.总结

操作是否指向同一个堆内存地址基本数据类型引用数据类型
赋值会改变会改变
浅拷贝不会改变会改变
深拷贝不会改变不会改变

6.Java 中创建对象的方式有哪几种?

(1)使用 new 关键字
这是最常见也是最简单的创建对象的方式,通过这种方式,我们可以调用任意的构造函数(无参的和有参的)。

public class Student {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

(2)通过反射机制
① 使用 Class 类中的 newInstance 方法
使用 Class 类中的 newInstance 方法创建对象。这个 newInstance 方法调用无参的构造函数创建对象。

public class Student {
    public static void main(String[] args) throws Exception {
        //使用 Class 类中的 newInstance 方法创建对象,有以下两种方式
        Student student1 = (Student) Class.forName("test.Student").newInstance();
        Student student2 = Student.class.newInstance();
        System.out.println(student1 == student2);           //false
    }
}

② Constructor 类中的 newInstance 方法
和 Class 类中的 newInstance 方法很像, java.lang.reflect.Constructor 类里也有一个 newInstance 方法可以创建对象。我们可以通过这个newInstance 方法调用有参数的和私有的构造函数。

public class Student {
    public static void main(String[] args) throws Exception {
        Constructor<Student> constructor = Student.class.getConstructor();
        Student student = constructor.newInstance();
    }
}

(3)使用 clone 方法
无论何时我们调用一个对象的 clone(),JVM 就会创建一个新的对象,将前面对象的内容全部拷贝进去。用 clone() 创建对象并不会调用任何构造函数。要使用 clone(),我们需要先实现 Cloneable 接口并实现其定义的 clone()。

public class Student implements Cloneable {
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        System.out.println("具体原型复制成功!");
        return (Student)super.clone();
    }
    
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student();
        Student student2 = (Student)student1.clone();
        System.out.println(student1 == student2);       //false
    }
}

(4)通过序列化机制
序列化就是把对象通过流的方式存储到文件中,此对象要重写 Serializable 接口才能被序列化。
反序列化就是把文件中的内容读取出来,还原为 Java 对象,该过程也需要实现 Serializable 接口。
当我们序列化和反序列化一个对象,JVM 会给我们创建一个单独的对象。在反序列化时,JVM 创建对象并不会调用任何构造函数。

public class Student implements Serializable {
    
    private int age;
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public static void main(String[] args) throws Exception {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("stu.txt"));
        Student student1 = new Student();
        student1.setAge(18);
        out.writeObject(student1);
        
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("stu.txt"));
        Student student2 = (Student) in.readObject();
        System.out.println(student2.getAge());              //18
	
		System.out.println(student1 == student2);           //false
    }
}

7.重写和重载的区别是什么?

(1)重写 (Override)
从字面上看,重写就是重新写一遍的意思。其实就是在子类中把父类本身有的方法重新写一遍。子类继承了父类原有的方法,但有时子类并不想原封不动的继承父类中的某个方法, 此时可以对方法体进行修改或重写。但需要注意以下几点,简称两同两小加一大原则:
① 方法名、参数列表相同;
② 子类返回类型小于等于父类方法返回类型、重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常
③ 子类函数的访问修饰权限要大于等于父类的 (public > protected > default > private)

public class Father {
    public void sayHello() {
        System.out.println("Hello, Father");	//Hello, Son
    }
    
    public static void main(String[] args) {
        Son s = new Son();
        s.sayHello();
    }
}

class Son extends Father{
    @Override
    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("Hello, Son");
    }
}

(2)重载 (Overload)
在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同甚至是参数顺序不同)则视为重载,它是一个类中多态性的一种表现。同时,重载对返回类型没有要求,可以相同也可以不同,但不能通过返回类型是否相同来判断重载。

public class Father {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Father s = new Father();
        s.sayHello();
        s.sayHello("wintershii");
    }
    public void sayHello() {
        System.out.println("Hello");
    }
    public void sayHello(String name) {
        System.out.println("Hello" + " " + name);
    }
}

8.Java 的四种引用方式分别是什么?

(1)强引用 (Strong Reference)
强引用是平常中使用最多的引用,在程序内存不足时也不会被垃圾收集器回收。

//使用方式
Object obj=new Object()

(2)软引用 (Soft Reference)
① 软引用在程序内存不足时会被回收。
② 可用场景: 创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM 就会回收早先创建的对象。

/*
	注意:wrf 这个引用也是强引用,它是指向 SoftReference 这个对象的,
	这里的软引用指的是指向new String("str")的引用,也就是 SoftReference 类中T
*/
SoftReference<String> wrf = new SoftReference<String>(new String("str"));

(3)弱引用 (Weak Reference)
① 弱引用就是只要 JVM 垃圾回收器发现了它,就会将其回收。
② 可用场景: Java 源码中 java.util.WeakHashMap 中的 key 就是使用弱引用,一旦我不需要某个引用,JVM 会自动帮忙处理它,这样我们就不需要做其它操作。

//使用方式
WeakReference<String> wrf = new WeakReference<String>(str);

(4)虚引用 (Phantom Reference)
① 虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入 ReferenceQueue 中。需要注意的是,其它引用是被 JVM 回收后才被传入 ReferenceQueue 中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。此外,虚引用创建的时候,必须带有ReferenceQueue。
② 可用场景: 对象销毁前的一些操作,比如说资源释放等。 Object.finalize() 虽然也可以做这类动作,但是这个方式即不安全又低效。

//使用方式
PhantomReference<String> prf = new PhantomReference<String>(new String("str"), new ReferenceQueue<>());

注意:上诉所说的几类引用,都是指对象本身的引用,而不是指 Reference 的四个子类的引用。

9.构造方法有哪些特点?

(1)名字必须与类名相同。
(2)没有返回值,也不能用 void 声明构造函数。
(3)生成类的对象时自动调用,且在整个对象的生命周期内只调用一次
(4)构造方法不能被 override(重写),但是可以 overload(重载),所以我们经常可以看到一个类中有多个构造方法的情况。
(5)如果用户没有显式定义构造方法,编译器就会默认生成一份构造方法,而且默认生成的构造方法一定是无参的。不过一旦用户定义了一个构造方法,编译器咋不会自动生成的构造方法。

10.抽象类 (abstract class) 和接口 (interface) 有什么共同点和区别?

(1)共同点

  • 都不能被实例化;
  • 都可以包含抽象方法;
  • 都可以有默认实现的方法(JDK 1.8 可以用 default 关键字在接口中定义默认方法);

(2)区别

  • 基本使用
    • 抽象类只能继承一个,接口可以实现多个,即单继承,多实现
    • 接口比抽象类更加抽象,因为抽象类中可以定义构造方法,可以有抽象方法和具体方法。而接口中不能定义构造方法,而且其中的方法全部都是抽象方法,默认且只能是 public abstract 的;
      在这里插入图片描述
    • 抽象类中可以定义静态块,而接口中则不能;
    • 抽象类中可以定义成员变量,并且接口中定义的成员变量实际上都是常量,默认且只能是 public static final 的;
      在这里插入图片描述
    • 有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法;
  • 设计目的
    • 接口的设计目的是对类的行为进行约束(更准确的说是一种"有"约束,因为接口不能规定类不可以有什么行为),也就是提供一种机制,可以强制要求不同的类具有相同的行为。它只约束了行为的有无,但不对如何实现行为进行限制。
    • 抽象类的设计目的是代码复用。当不同的类具有某些相同的行为(记为行为集合 A),且其中一部分行为的实现方式一致时(A的非真子集,记为B),可以让这些类都派生于一个抽象类。在这个抽象类中实现了 B,避免让所有的子类来实现 B,这就达到了代码复用的目的。而 A - B 的部分,留给各个子类自己实现。正是因为 A - B 在这里没有实现,所以抽象类不允许实例化出来(否则当调用到 A - B 时,无法执行)。
  • 设计思想
    • 抽象类是对类本质的抽象(自下而上),表达的是 is xxx 的关系,比如: BMW is a car。抽象类包含并实现子类的通用特性,将子类存在差异化的特性进行抽象,交由子类去实现。
    • 而接口是对行为的抽象(自上而下),表达的是 like xxx 的关系。比如:Bird like a Aircraft(像飞行器一样可以飞),但其本质上 is a Bird。接口的核心是定义行为,即实现类可以做什么,至于实现类主体是谁、是如何实现的,接口并不关心。
  • 使用场景:当关注事物的本质时,使用抽象类;当关注事物的操作时,使用接口。
  • 复杂度:抽象类的功能要远超过接口,但是定义抽象类的代价比较高。因为对于Java来说,每个类只能继承一个类,在这个类中,你必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口,在设计阶段会降低难度。

11.什么是内部类?为什么需要使用内部类?

(1)简单来说,内部类 (inner class) 是定义在另一个类中的类

(2)使用内部类的主要原因有以下三点:
① 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。
② 内部类可以对同一个包中的其他类隐藏起来。
③ 当想要定义一个回调函数且不想编写大量代码时,使用匿名 (anonymous) 内部类比较便捷。

12.匿名内部类可以继承类或实现接口吗?为什么?

(1)匿名内部类本质上是对父类方法的重写或对接口方法的实现。从语法角度看,匿名内部类创建处无法使用关键字继承类或实现接口

(2)原因如下:
① 匿名内部类没有名字,所以它没有构造函数。因为没有构造函数,所以它必须通过父类的构造函数来实例化。即匿名内部类完全把创建对象的任务交给了父类去完成。
② 匿名内部类里创建新的方法没有太大意义,新方法无法被调用。
③ 匿名内部类一般是用来覆盖父类的方法。
④ 匿名内部类没有名字,所以无法进行向下的强制类型转换,只能持有匿名内部类对象引用的变量类型的直接或间接父类。

13.说说内存中的栈 (stack)、堆 (heap) 和静态存储区的用法。

(1)通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间
(2)通过 new 关键字和构造器创建的对象放在堆空间
(3)程序中的字面量 (literal) 如直接书写的 100、“hello, world” 和常量都是放在静态存储区中。
(4)栈空间操作最快但是也很小,通常大量的对象都是放在堆空间,整个内存包括硬盘上的虚拟内存都可以被当成堆空间来使用。
(5)String str = new String(“hello”);
上面的语句中 str 放在栈中,用 new 创建出来的字符串对象放在堆中,而 “hello” 这个字面量放在静态存储区,一共创建了两个字符串对象。

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

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

相关文章

Qt代码单元测试以及报告生成

简介 单元测试是所有测试中最底层的一类测试&#xff0c;是第一个环节&#xff0c;也是最重要的一个环节&#xff0c;是唯一一次有保证能够代码覆盖率达到100%的测试&#xff0c;是整个软件测试过程的基础和前提&#xff0c;单元测试防止了开发的后期因bug过多而失控&#xff0…

< elementUi 组件插件: el-table表格拖拽修改列宽及行高 及 使用注意事项 >

elementUi 组件插件&#xff1a; el-table拖拽修改列宽及行高 及 使用注意事项&#x1f449; 资源Js包下载及说明&#x1f449; 使用教程> 实现原理> 局部引入> 全局引入 &#xff08;在main.js中&#xff09;&#x1f449; 注意事项往期内容 &#x1f4a8;&#x1f4…

Android Studio adb命令

Android Studio在IP连接142的手机进行无线调试 adb tcpip 5555 // 端口 adb shell ifconfig wlan0 //查看ip adb connect 192.168.1.142:5555 当已经连接上142这个ip&#xff0c;还想再连接其他143这个ip 方法如下&#xff1a; adb devices -l 查看当前设备 adb …

直接下载docker镜像包

这周正在做APIcat的企业版研发&#xff0c;准备适配阿里云的计算巢提供企业直接云安装的功能&#xff0c;顺便把原来写过的一个直接下载docker镜像包的小程序挂到了Gitee上面&#xff0c;有需要的可以点击下载 https://gitee.com/extrame/dgethttps://gitee.com/extrame/dget …

安灯呼叫系统助力企业实现精益管理

在当前的生产企业管理过程当中&#xff0c;生产现场难免会出现各种异常情况影响生产&#xff0c;乳设备需要机修、品质问题、物料呼叫等各种情况&#xff0c;在以往这些问题出现过后处理的方式都是些申请单&#xff0c;由人工到各个部门去给领导签字&#xff0c;浪费大量时间沟…

【Unity VR开发】结合VRTK4.0:远距离抓取物体

语录&#xff1a; 我们都生活在阴沟里&#xff0c;但仍有人仰望星空。 前言&#xff1a; 空间场景中的一个常见问题是试图抓取一个无法触及或太远而无法到达的对象。VRTK提供了一种简单的方法来实现这种技术&#xff08;Interactions.PointerInteractors.DistanceGrabber&…

上市公司每股社会贡献值(数据+代码)(2000-2020年)

数据来源&#xff1a;自我整理 时间跨度&#xff1a;2000-2020年 区域范围&#xff1a;上市公司 指标说明&#xff1a; 每股社会贡献值( 净利润所得税费用营业税金及附加支付给职工以及为职工支付的现金本期应付职工薪酬-上期应付职工薪酬财务费用捐赠-排污费及清理费) / 期…

MySQL服务器体系架构 执行原理

前言 前边我们了解了MySQL采用客户端/服务器架构&#xff0c;用户通过客户端程序发送增删改查需求&#xff0c;服务器程序收到请求后处理&#xff0c;并且把处理结果返回给客户端。这篇文章主要看下MySQL服务端是如何处理客户端的请求&#xff0c;感兴趣的小伙伴们可以参考借鉴…

【单目标优化算法】烟花优化算法(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

定时器设计

定时器设计 定时器应用&#xff1a; 游戏的Buff实现&#xff0c;Redis中的过期任务&#xff0c;Linux中的定时任务等等心跳检测&#xff0c;如服务器接收队列满了&#xff0c;tcp客户端会定时探测是否能够发送数据 定时器数据结构选取要求&#xff1a; 需要快速找到到期任务…

防火墙设置实验(12)

预备知识防火墙基本原理 防火墙是一种访问控制技术&#xff0c;位于可信与不可信网络之间&#xff0c;通过设置一系列安全规则对两个网络之间的通信进行控制&#xff0c;检测交换的信息&#xff0c;防止对信息资源的非法存取和访问。防火墙分为软防火墙和硬防火墙&#xff0c;一…

关于分布式的一些基础知识

1、分布式锁 (ngix,zoomkeeper,raft,kafka) 在单机场景下&#xff0c;可以使用语言的内置锁来实现进程或者线程同步。但是在分布式场景下&#xff0c;需要同步的进程可能位于不同的节点上&#xff0c;那么就需要使用分布式锁。 为了保证一个方法或属性在高并发情况下的同一时间…

【面试题】前端春招第二面

不容错过的一些面试题小细节&#xff0c;话不多说&#xff0c;直接看题~大厂面试题分享 面试题库后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库HTML/CSS/Javascript/ES篇&#xff08;1&#xff09;标准盒模型和怪异盒…

k8s集群概念组件简介

一、Kubernetes 集群概述1.2 Kubernetes 资源资源用途服务&#xff08;Service&#xff09;Kubernetes 使用服务在一组 pod 上公开正在运行的应用程序。ReplicaSetKubernetes 使用 ReplicaSet 来维护恒定的 pod 号。Deployment维护应用程序生命周期的资源对象。1.3 Kubernetes …

重生之我是赏金猎人-SRC漏洞挖掘(七)-看我如何从FUZZ到SRC官网XSS

0x01 前奏 本文来自&#xff1a;RGM78sec 截至发稿&#xff0c;vuln早已修复 前不久在挖掘某SRC时&#xff0c;偶然在该SRC官网的编辑器发现了一个接口。 起初以为是任意文件包含能RCE了&#xff0c;后来测试发现只是拼接读取了远程资源站的图片&#xff0c;原本都想着放弃…

TypeScript(二)基本数据类型

前言 距离上篇博客已有两年了&#xff0c;对TS也有了一定的认识&#xff0c;于是计划继续更新系列文章 基本数据类型 在JS中&#xff0c;基本数据类型有&#xff1a;Boolan&#xff08;布尔&#xff09;&#xff0c;Number&#xff08;数字&#xff09;&#xff0c;String&a…

什么是事务?Mysql事务怎么用?Mybatis怎么操作事务的?Spring呢?快进来看看

目录 一、计算机中的事务 1. 概念 2.事务的ACID特性 3.事务类型 1)手动事务 2)自动事务 4.为什么需要事务? 5.优点 二、MySQL事务 1.语法格式: 2.关闭自动提交&#xff0c;开启新事务 3.开启自动提交&#xff0c;关闭事务控制 三、Mybatis事务 Mybatis开关事务控…

Meta AR眼镜主管:正开发史无前例的AR,但要解决很多困难

前不久&#xff0c;Meta CTO Andrew Bosworth在个人博客上“怒斥”公司内部不够专注&#xff0c;应该将资源投入在有核心竞争力、高投资回报率的业务上&#xff0c;而不是开发取悦用户却不赚钱的产品。尽管删除一些小众功能后&#xff0c;用户可能会不满&#xff0c;但为了让Me…

Bi系统跟数据中台的区别是什么?

随着数据时代的发展&#xff0c;BI分析是当今数据时代必不可少的能力之一。BI系统通过系统化产品化的方法&#xff0c;能够大幅降低数据的获取成本、提升数据使用效率。同时借助可视化、交互式的操作&#xff0c;可以高效支持业务的分析及发展。 BI如此火热&#xff0c;随之而…

openpnp - 增加散料飞达

文章目录openpnp - 增加散料飞达概述笔记飞达在设备上的放置方向编带料在飞达中的方向将相机移动到飞达料的第一孔的中心捕获保存第1孔中心编带设置测试相机位置是否正确测试吸嘴的位置是否正确将吸嘴回到安全位置测试是否能正确抓料ENDopenpnp - 增加散料飞达 概述 使用open…