[Java基础]Java总结篇

超详细的Java面试题汇总(基础篇+框架篇) Java面试题汇总-基础篇 1.面向对象是什么? 答:面向对象是一种思想,世间万物都可以看做一个对象,这里只讨论面向对象编程(OOP),Java是一个支持并发、基于类和面向对象的计算机编程语言,面向对象软件开发的优点:代码开发模块化,更易维护和修改;代码复用性强;增强代码的可靠性和灵活性;增加代码的可读性。 2、String 是最基本的数据类型吗? 答:不是。Java中的基本数据类型只有8个:by... 阅读详情

本文来自于清华大神(潇涧)的Java总结,已得到其本人允许转载


1.JVM


JVM内存模型:


PC(程序计数器),虚拟机栈,本地方法栈,Java堆,方法区

PC:字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

虚拟机栈:每个方法被执行的时候都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接方法、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个帧栈在虚拟机栈中从入栈到出栈的过程。局部变量所需的内存空间在编译期间完成分配。当进入一个方法时,这个方法需要在帧中分配多大的局部变量是完全确定的,在方法运行区间不会改变。

本地方法栈:虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法则是为虚拟机使用到的Native方法服务。如果从内存分配的角度看,线程共享的Java堆可能划分出多个线程私有的分配缓冲区(ThreadLocalAllocationBuffer)。

Java堆:几乎所有的对象和数组都是在堆中分配空间的,分为老生代和新生代,新生代可分为eden,survivor space 0,survivor space 1

方法区:它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,其信息大部分来自class文件。在Hot spot虚拟机中,方法区也叫永久区,但是也会被GC,GC主要有两类:对常量池的回收,对类元数据的回收。

如果VM确认所有该类的实例都被回收并且装载该类的类加载器也被回收了,那么就回收该类的元数据。

运行时常量池(Runtime Constant Pool)是方法区的一部分。(不一定)

Java语言并不要求常量一定只能在编译期产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用的比较多的便是String类的intern()方法。

JVM参数:设置最大堆内存Xmx,最小堆内存Xms,新生代大小Xmn,老年代大小PermSize,线程栈大小Xss,新生带eden和s0空间大小比例以及老年代和新生代的空间大小比例

垃圾回收算法


(1)引用计数法:缺点是无法处理循环引用问题

(2)引用-清除法:标记所有从根结点开始的可达对象,清除所有未标记的对象,缺点是会造成内存空间不连续,不连续的内存空间的工作效率低于连续的内存空间,不容易分配内存

(3)复制算法:将内存空间分为两块,每次将正在使用的内存中的存活对象复制到未使用的内存块中,之后清除正在使用的内存块算法效率高,但是代价是将系统内存折半。适用于新生代(存活对象少,垃圾对象多)

(4)标记-压缩算法:标记-清除的改进,清除未标记的对象时还将所有的存活对象压缩到内存的一端,之后,清除边界外所有空间既避免碎片产生,又不需要两块同样大小的内存快,性价比高。适用于老年代。

(5)分代

JVM–标记-清除算法Mark-Sweep

首先是mutator和collector,这两个名词经常出现在垃圾收集回收算法中出现,collector指的就是垃圾收集器,而mutator是指除了垃圾收集器以外的部分,比如说我们程序本身。mutator的职责一般是NEW(分配内存),READ(从内存中读取内容),WRITE(将内容写入内存),而Collector则就是回收不再使用的内存来供mutator进行NEW操作的使用。

第二个概念是关于mutator roots(mutator根对象),mutator根对象一般指的是分配在堆内存之外,可以直接被mutator直接访问到的对象,一般是指静态/全局变量以及Thread-Local变量(在Java中,存储在java.lang.ThreadLocal中的变量和分配在栈上的变量-方法内部的临时变量都属于此类)。

第三个概念是关于可达对象的定义,从mutator根对象开始进行遍历,可以被访问到的对象都称为是可达对象。这些对象也是mutator(你的应用程序)正在使用的对象。

垃圾回收器的类型


(1)线程数:串行,并行 并行:开启多个线程同时进行垃圾回收,缩短GC停顿时间

(2)工作模式:并发,独占 并发:垃圾回收线程和应用程序线程交替工作

(3)碎片处理:压缩,非压缩

(4)分代:新生代,老年代

CMS:Concurrent Mark Sweep 并发标记清除,减少GC造成的停顿时间
过程:初始标记,并发标记,重新标记,并发清理,并发重置

2.多线程


参考文章

JAVA多线程和并发基础面试问答(转载)

生产者和消费者:

Java BlockingQueue Example implementing Producer Consumer Problem | JournalDev

Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

java.util.concurrent.BlockingQueue的特性是:当队列是空的时,从队列中获取或删除元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。

阻塞队列不接受空值,当你尝试向队列中添加空值的时候,它会抛出NullPointerException。

阻塞队列的实现都是线程安全的,所有的查询方法都是原子的并且使用了内部锁或者其他形式的并发控制。

BlockingQueue接口是java collections框架的一部分,它主要用于实现生产者-消费者问题。

线程调度器是一个操作系统服务,它负责为Runnable状态的线程分配CPU时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。时间分片是指将可用的CPU时间分配给可用的Runnable线程的过程。分配CPU时间可以基于线程优先级或者线程等待的时间。线程调度并不受到Java虚拟机控制,所以就是说不要让你的程序依赖于线程的优先级。

线程之间如何通信的?当线程间是可以共享资源时,线程间通信是协调它们的重要手段。Object类中wait()/notify()/notifyAll()方法可以用于线程间通信关于资源的锁的状态。

如何确保线程安全?在Java中可以有很多方法来保证线程安全-同步,使用原子类(atomic concurrent classes),实现并发锁(Lock),使用volatile关键字,使用不变类和线程安全类。

Lock设置文件共享锁,Lock确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

vilatile并不能保证线程安全 jvm虚拟机栈->线程栈->方法栈

jvm有一个内存区域是jvm虚拟机栈,每一个线程运行都有 一个线程栈,线程栈保存了线程运行时变量值信息。当线程访某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的值load到线程本地内存中,建立一个副本,之后线程就不再和对象堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。

当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其他线程对该object对象所有的同步代码部分的访问都被暂时阻塞。

synchronized方法控制对类成员的变量的访问:每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的类实例锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为synchronized的成员函数中国至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为synchronized)。同步函数使用的锁是this,静态同步函数的锁是该类的字节吗文件对象。

synchronized块是这样一个代码块,其中的代码必须获得对象syncObject(如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。利用同步代码块可以解决线程安全问题。

等待唤醒机制

wait:将同步中的线程处于冻结状态。释放了执行权,释放了资格,同时将线程对象存储到线程池中。

notify:唤醒线程池中某一个等待线程。notifyAll:唤醒的是线程池中的所有线程。

notify和notifyAll到底哪个先执行?

  1. 这些方法都需要定义在同步中。
  2. 这些方法必须要标示所属的锁。要知道A锁上的线程被wait了,那这个线程就相当于处于A锁的线程池中,只有A锁的notify醒。
  3. 这三个方法都定义在Object类中。

为什么操作线程的方法定义在object类中?因为这三个方法都需要定义同步内,并标示所属的同步锁,既然被锁调用,而锁又可以是任意对象,那么能被任意对象调用的方法一定定义在Object类中。

wait和sleep区别,从执行权和锁上来分析:

wait:可以指定时间也可以不指定时间。不指定时间,只能由对应的notify或者notifyAll来唤醒。
wait:线程会释放执行权,而且线程会释放锁。
sleep:必须指定时间,时间到自动从冻结状态blocked转成运行状态(临时阻塞状态)。
sleep:线程会释放执行权,但不释放锁。

  1. NEW:这种情况指的是,通过NEW关键字创建了Thread类(或其子类)的对象
  2. RUNNABLE:这种情况指的是Thread类的对象调用了start()方法,这时的线程就等待时间片轮转到自己这,以便获得CPU;第二种情况是线程处于RUNNABLE状态时并没有运行完自己的run方法,时间片用完之后回到RUNNABLE状态;还有种情况是处于BLOCKED状态结束了当前的BLOCKED状态之后重新回到RUNNABLE状态。
  3. RUUNING:这时的线程指的是获得CPU的RUNNABLE线程,RUNNING状态是所有线程都希望获得的状态。
  4. DEAD:处于RUUNING状态的线程,在执行完run方法之后,就变成了DEAD状态了。
  5. BLOCKED:这种状态指的是处于RUNNING状态的线程,处于某种原因,比如调用了sleep方法、等待用户输入等让出当前的CPU给其他的线程。

处于RUNNABLE状态的线程变为BLOCKED状态的原因,除了该线程调用了sleep方法、等待输入原因外,还有就是在当前线程中调用了其他线程的join方法、当访问一个对象的方法时,该方法被锁定等。

相应的,当处于BLocked状态的线程再满足一下条件时就会由该状态转到RUNNABLE状态,这些条件是:sleep的线程醒来(sleep的时间到了)、获得了用户的输入、调用了join的其他线程结束、获得了对象锁。

一般情况下,都是处于RUNNABLEd的线程和处于RUNNABLE状态的线程,互相切换,直到运行完run方法,线程结束,进入DEAD状态。

3.集合框架

List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
|–ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快。
|–LinkedList:底层的结构是链表,线程不同步,增删的速度非常快
|–Vector:底层的数据结构就是数组,线程同步的,Vector 无论查询和增删都巨慢

可变长度数组的原理:当元素超出数组长度,会产生一个新的数组,将原数组复制到新数组中,再将新的元素添加到新数组中。

ArrayList:是按照原数组的50%延长。构造一个初始容量为10的空列表。

Vector:是按照原数组的100%延长

Set 接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器。
|–HashSet:底层数据结构是哈希表,线程是不同步的。无序,高效;
|–LinkedHashSet:有序,hashset的子类
|–TreeSet:对Set集合中的元素进行指定顺序的排序。不同步。TreeSet底层的数据结构就是二叉树。

HashSet集合保证元素唯一性:通过元素的hashCode方法和equals完成的。当元素的hashCode值相同时,才继续判断元素的equals是否为true。如果为true,那么视为相同元素,不存。如果为false,那么存储。如果hashCode值不同,那么不判断equals从而提高对象比较的速度。

对于ArrayList集合,判断元素是否存在,或者删除元素底层依据都是equals方法。

对于HashSet集合,判断元素是否存在,或者删除元素,底层依据是hashCode方法和equals方法。

4.常用的设计模式

(1)单例模式:实现方式很多,最常见的方式就是将构造函数设置为private,类中保存一个private的静态单例对象,然后新建一个public static的函数例如getInstance,在这个方法中返回静态单例对象。如果考虑到延迟加载,为了在多线程环境保持单例需要同步关键字,但是这样做反而会增加时耗。最好的实现方式:使用内部类来维护单例的实例。

当StaticSingleton被加载的时候,其内部类并不会被初始化,所以实例也不会被初始化。而当getInstance方法被调用时,才会加载SingletonHolder,从而初始化instance。同时,由于实例的加载是在类加载时完成的,天生对线程友好,getInstance方法不需要使用同步关键字。(类加载自身处理了多线程环境下的同步问题)

//双重判断的方式
class Single
{
    private static Single s = null;
    private Single(){}
    public static Single getInstance()
    {
        if(s == null)
        {
            syncronized(Single.class)
            {
                if(s == null)
                {
                    s = new Single();
                }
            }
        }
        return s;
    }
}
public class StaticSingleton
{
    private StaticSingleton()
    {
    }

    private static class SingletonHolder
    {
        private static StaticSingleton instance = new StaticSingleton();
    }

    public static StaticSingleton getInsatnce()
    {
        return SingletonHolder.instance;
    }
}

(2)代理模式

使用场景:(1)延迟加载,对真实对象进行封装;(2)网络代理,RMI;(3)安全代理,屏蔽客户端直接访问真实对象

延迟加载的核心思想:在真正需要某个组件的时候才去对它进行加载,其他时候使用代理对象即可,这样可以有效提高系统启动速度。多线程编程模式中的Future模式就是使用了代理模式,一般情况下都会有个接口,真实对象和代理对象都实现了这个接口。

动态代理:使用字节码动态生成加载技术,在运行时生成并加载类。应用场景:在运行时动态生成并加载代理类,与静态代理相比,这样做的好处就是不用为每个真实对象生成一个形式上一样的封装类,如果要修改就都要修改。

工具:JDK自带,CGLib,Javasist

(3)享元模式:如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一次使用都创建新的对象。类似线程池,但是不同的是前者保存的对象是不可以互相替换的,而后者可以。

(4)装饰者模式:通过委托机制,复用系统中的各个组件,在运行时,可以将这些功能组件进行叠加,使其拥有所有这些组件的功能。被装饰者是系统的核心组件,装饰者可以在被装饰者的方法前后加上特定的前置处理和后置处理,增强被装饰者的功能。

使用场景:JDK的IO框架、输出html内容

(5)观察者模式:在单线程中使某一个对象及时得知自身所依赖的状态变化。实现将观察者添加到被观察者维护的观察者列表即可。

5.Java中的4种引用类型

  • 强引用:JVM宁愿抛出OOM也不会将它回收,可能导致内存泄漏
  • 软引用:当内存空间不足的时候才会去回收软引用的对象
  • 弱引用:在系统GC时,弱引用的对象一定会被回收,软弱引用适合保存那些可有可无的缓存数据
  • 虚引用:虚引用跟没有引用差不多,即时强引用对象还存在,get方法总是返回null,它最大的作用就是跟踪对象回收,清理被销毁对象的相关资源

WeakHashMap适用场景:如果系统需要一张很大的map表,map中的表项作为缓存之用,即使没能从map中拿到数据也没关系的情况下。一旦内存不足的时候,weakhashmap会将没有被引用的表项清除掉,从而避免内存溢出。它是实现缓存的一种特别好的方式。实现:Entry

6.类加载过程

                ======  常见面试问题  =======

1、equals和==的区别:前者是由对象的equals方法决定的,后者是判断两个对象指向的内存空间的地址是否相同

2、string.intern方法,在JDK6中常量池是方法区的一部分,在JDK6中常量池是方法区的一部分,在JDK7及以上常量池放到了Java堆中。

intern方法调用时首先去常量池找这个字符串,如果有就将该字符串的引用返回,如果没有就创建该字符串放到池中然后返回引用

String s = “11”; //在常量池中创建字符串11,并把它的引用赋给s

String s = new String(“11”); //在常量池中创建字符串11,在堆中创建一个对象c,它指向常量池中的字符串,而s指向c

3、执行顺序:(优先级从高到低)静态代码块>main方法>构造代码块>构造方法

其中静态代码块只执行一次。构造代码块在每次创建对象都会执行。

4、final

  • 这个关键字是一个修饰符,可以修饰类、方法、变量
  • 被final修饰的类是一个最终类,不可以被继承
  • 被final修饰的方法是一个最终方法,不可以被覆盖
  • 被final修饰的变量是一个常量,只能赋值一次

5、抽象类与接口的区别

  • 抽象类只能被继承,而且只能单继承。接口需要被实现,而且可以多实现。
  • 抽象类中可以定义非抽象方法,子类可以直接继承使用。接口中都是抽象方法,需要实现类去实现。
  • 抽象类使用的是 is a 关系。接口使用的 like a 关系。
  • 抽象类的成员修饰符可以自定义
  • 接口中的成员修饰符是固定的,全都是public的。

6、如果内部类被静态修饰,相当于外部类,会出现访问局限性,只能访问外部类中的静态成员。

注意:如果内部类中定义了静态成员,那么该内部类必须是静态的。内部类编译后的文件名为:”外部类名$内部类名.java”。

为什么内部类可以直接访问外部类中的成员呢?

那是因为内部中都持有外部类的引用。这个引用是 外部类名.this。内部类可以定义在外部类中的成员位置上,也可以定义在外部类中的局部位置上。当内部类被定义在局部位置上,职能访问局部中被final修饰的局部变量。

7、HashMap和HashTable的区别:

  • hashtable是线程安全的
  • hashtable不允许key或者value为null,hashmap可以
  • 在内部算法上,它们对key的hash算法和hash值到内存索引的映射算法不同。

8、hashcode和equals方法

在一个运行的进程中,相等的对象必须要有相同的哈希码;不同的对象可以有相同的哈希码

  1. 无论你何时实现equals方法,你必须同时实现hashCode方法
  2. 永远不要把哈希码误用作为key,哈希冲突是件很正常的事情,hashmap中的contains方法的实现!
  3. 哈希码可变,hashcode并不保证在不同的应用执行中得到相同的结果
  4. 在分布式应用中不要使用哈希码

替代哈希码:SHA1,加密的哈希码,160位秘钥,冲突几乎是不可能的。

9、RuntimeException和其他Exception的区别

Error体系:Error体系描述了Java运行系统中的内部错误以及资源耗尽的情形。应用程序中不应该抛出这种类型的对象(一般是由虚拟机抛出)。如果出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以,在进行程序设计时,应该更关注Exception体系。

Exception体系包括RuntimeException体系和其他非RuntimeException的体系:

  1. RuntimeException:RuntimeException体系包括错误的类型转换、数组越界和试图访问空指针等等。处理RuntimeException的原则是:如果出现RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。
  2. 其他非RuntimeException(IOException等等):这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。

10、集合框架

这里写图片描述

生产者与消费者


public class ProducerConsumerTest {
    public static void main(String[] args) {
        PublicResource resource = new PublicResource();
        new Thread(new ProducerThread(resource)).start();
        new Thread(new ConsumerThread(resource)).start();
        new Thread(new ProducerThread(resource)).start();
        new Thread(new ConsumerThread(resource)).start();
        new Thread(new ProducerThread(resource)).start();
        new Thread(new ConsumerThread(resource)).start();
    } 
}


/** 
 * 生产者线程,负责生产公共资源  
 */
class ProducerThread implements Runnable {
    private PublicResource resource;
    public ProducerThread(PublicResource resource) {
        this.resource = resource;
    }
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep((long) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            resource.increase();
        }
    } 
}

/**
 * 消费者线程,负责消费公共资源
 */
class ConsumerThread implements Runnable {
    private PublicResource resource;
    public ConsumerThread(PublicResource resource) {
        this.resource = resource;
    }
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep((long) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            resource.decrease();
        }
    } 
}


/**
 *  公共资源类
 */
class PublicResource {
    private int number = 0;
    private int size = 10;
    /**
     *  增加公共资源  
     */
    public synchronized void increase() {
        while (number >= size) {
            try { 
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } 
        }
        number++;
        System.out.println("1" + number); 
        notifyAll();
        }
        /**
         *  减少公共资源
         */
        public synchronized void decrease() {
            while (number <= 0) {
                try { 
                    wait();
                } catch (InterruptedException e) {
                e.printStackTrace();
                } 
            }
            number--;
            System.out.println("1" + number); notifyAll();
        }
 }

实现LRU Cache

public class LRUCache {
    private class Node{
        Node prev;
        Node next;
        int key;
        int value;
        public Node(int key, int value) {
            this.key = key;
            this.value = value;
            this.prev = null;
            this.next = null;
        } 
    }
    private int capacity;
    private HashMap<Integer, Node> hs = new HashMap<Integer, Node>();
    private Node head = new Node(-1, -1);
    private Node tail = new Node(-1, -1);
    public LRUCache(int capacity) {
        this.capacity = capacity;
        tail.prev = head;
        head.next = tail;
    }
    public int get(int key) {
        if( !hs.containsKey(key)) {
        return -1; 
        }
        // remove current
        Node current = hs.get(key);
        current.prev.next = current.next;
        current.next.prev = current.prev;
        // move current to tail
        move_to_tail(current);
        return hs.get(key).value;
    }
    public void set(int key, int value) {
        if( get(key) != -1) {
            hs.get(key).value = value;
            return; 
        }
        if (hs.size() == capacity) {
            hs.remove(head.next.key);
            head.next = head.next.next;
            head.next.prev = head;
        }
        Node insert = new Node(key, value);
        hs.put(key, insert);
        move_to_tail(insert);
        }
    private void move_to_tail(Node current) {
        current.prev = tail.prev;
        tail.prev = current;
        current.prev.next = current;
        current.next = tail;
        } 
}
Java内存马攻防实战——攻击基础篇 在红蓝对抗中,攻击方广泛应用webshell等技术在防守方提供的服务中植入后门,防守方也发展出各种技术来应对攻击,传统的落地型webshell很容易被攻击方检测和绞杀。而内存马技术则是通过在运行的服务中直接插入运行攻击者的webshell逻辑,利用中间件的进程执行某些恶意代码,而不依赖实体文件的存在实现的服务后门,因此具有更好的隐蔽性,也更容易躲避传统安全监测设备的检测。 本文以Java语言为基础讨论内存马技术的攻防,分为两个篇章,分别是攻击基础篇和防护应用篇。本篇攻击基础篇介绍了Java Servlet 阅读详情

相关推荐

Java语言程序设计基础篇 第八章 课后编程答案

  原博链接:Java语言程序设计基础篇 第八章 课后编程答案   import java.util.Scanner; public class ch0801{ public static void main( String[] args ){ Rectangle r1 = new Rectangle(4,40) ; Rectangle r2 = new Rectangle(3...

u010717079的专栏 1万+

【Java基础知识 1】Java入门级概述,让阿里架构师告诉你为什么要分库分表

1998年12月8日,第二代Java平台的企业版J2EE发布。 1999年4月27日,HotSpot虚拟机发布。 2005年6月,在Java One大会上,Sun公司发布了Java SE 6。此时,Java的各种版本已经更名,已取消其中的数字2,如J2EE更名为JavaEE,J2SE更名为JavaSE,J2ME更名为JavaME。 2009年,甲骨文公司宣布收购Sun。 2014年3月Oracle发布正式版JDK8,JDK8改进比较多,最大的改进是Lambda表达式(以及因之带来的函数式接口,很多原有类都做

m0_64383736的博客 9949

树莓派与无人机协同实战:基于OpenCV的地标识别优化策略

本文深入探讨了基于树莓派与无人机的协同系统,重点分享了利用OpenCV优化地标识别以实现精准降落的实战策略。内容涵盖从应对复杂光照的图像预处理、鲁棒的轮廓几何过滤,到通过ROS进行稳定通信,以及实现分层控制与状态机设计,旨在提升系统在真实环境中的可靠性与性能。

y2z3a4b5c的博客 1085

Java 入门 (超级详细)

Java是一种高级编程语言,由Sun Microsystems公司于1995年推出。Java具有跨平台性、面向对象、健壮性、安全性、可移植性等特点,被广泛应用于企业级应用开发、移动应用开发、大数据处理、云计算等领域。Java程序可以在不同的操作系统上运行,只需编译一次,就可以在任何支持Java虚拟机(JVM)的平台上运行。Java还提供了丰富的库和框架,可以加快开发过程,提高开发效率。变量是计算机程序中用于存储数据的一种数据类型。它是一个名称,代表了一个值或一个对象,可以在程序中多次使用。

qq_63519395的博客 10万+

多周期路径及set_multicycle_path详解

默认情况下,每条路径都被定义为单周期,即源触发器在时钟的任一边沿启动(launch)的数据都应该由目的触发器在时钟的下一上升沿捕获(capture)。 有的设计需要在数据被捕获前提供一些额外的周期,这类路径被称为多周期路径。 一、set_multicycle_path命令 命令格式如下: set_multicycle_path .........

Jackiezhang1993的博客 4万+

RKDevTool解包和打包(Windows)

我们将修改后的打包工具存放在了RKDevTool_Release_v2.92软件压缩包的rockdev目录下,可以搭配RKDevTool的解包功能使用。双击板卡主芯片对应的bat文件,开始进行打包。红框中的内容是我们的打包工具及辅助打包的可执行文件,Image目录下存放了我们的分区镜像, package-file是分区与分区镜像文件的对应关系。将从网盘获取的Update.zip镜像解压成.img格式并重命名为update.img,也可以直接使用SDK生成的update.img镜像。

tianpu2320959696的博客 3348

java语言基础知识(完整版)

(5).JAVA_HOME指明JDK安装路径,例如刚刚安装时所选择的路径D:/java/jdk1.8.0_08,此路径下包括lib,bin,jre等文件夹;(7).键入命令“javac”,“java”,“java -version”几个命令,出现画面,说明环境变量配置成功即环境变量配置成功;原文链接:https://blog.youkuaiyun.com/Healer_xiaozhen/article/details/108186961。//编译错误,变量m未声明。

华仔的博客 1万+

华为海思:大小海思的双轮驱动战略分析

大海思的定位清晰明确,即专注于为华为内部提供高性能、高集成度的芯片解决方案,以支持华为终端、服务器等业务的快速发展。小海思的产品线广泛,涵盖了广域物联、短距物联、手机穿戴、显示交互、智慧视觉、智慧媒体、MCU、模拟以及光模块等多个领域。通过提供多样化的芯片解决方案,小海思旨在满足外部客户的不同需求,拓展华为海思在芯片市场的份额和影响力。大海思的产品布局主要围绕华为的内部需求展开。在智能手机应用处理器方面,大海思的麒麟系列芯片已经成为华为手机的标志性产品,以其出色的性能和能效比赢得了市场的广泛认可。

dream it possible 2922

java编程基础(入门级)(超级完整版)

java基础编程 01基础知识 1.计算机基础 【1】进制 A.十进制转化二进制 除以2,求余数,商继续除以2,一直到0为止,从底下往上得到结果。 B.二进制转化十进制 1 | 1 | 0 | 0 23∣22∣21∣202^3 | 2^2 | 2^1 | 2^023∣22∣21∣20 8+4+0+0=128+4+0+0=128+4+0+0=12 【2】 计算机的储存方式 位(bit):0或1 字节(byte):8位1字节,数据储存的最小单位 1 KB=1024 Byte 1 MB=1024 KB 1 GB=

weixin_41406651的博客 6万+

ADAS工作原理解析:如何通过智能技术提升驾驶安全

ADAS通过集成传感器、摄像头、雷达、SoC计算单元以及高效的数据融合技术,提供了一系列主动和被动安全功能,如自动刹车、车道保持、自适应巡航控制等。这些功能共同作用,不仅减少了交通事故的发生,还大幅提升了驾驶员的驾驶体验和安全性。随着技术的进步,ADAS的功能将越来越智能,最终迈向全自动驾驶的未来🚗💨。

weixin_43199439的博客 1148

ansys非线性分析中接触类型

不分离(No Separation)‌:法向始终保持接触不分离,切向允许自由滑动,属于线性接触,适合需要法向约束、允许微小切向位移的场景,比如过盈配合的简化模拟。有摩擦(Frictional)‌:法向允许分离,切向根据用户设置的摩擦系数计算摩擦力,是工程中最符合实际机械接触的类型,绝大多数装配体分析都选择该类型。无摩擦(Frictionless)‌:法向允许接触面分离,切向无摩擦、允许自由滑动,适合模拟理想润滑的光滑接触面,图中当前选择的就是该类型。非线性接触(需要多次迭代,属于真正的非线性接触行为)‌。

qq_15963745的博客 71

java基础知识汇总

数组就是存储数据长度固定的容器,存储多个数据的数据类型要一致。1.2.1第一种数据类型[] 数组名示例:int[] arr;char[] arr;1.2.2第二种数据类型 数组名[]示例:int arr[];char arr[];

Relievedz的博客 1万+

图像增强算法:基于Retinex的图像增强算法

该算法对图像的亮度和颜色进行分离处理,然后通过调整它们的比例来提高图像的质量。滤波后的图像将保留颜色信息,并减少图像中的噪声。接下来,Retinex算法使用一个高通滤波器对原始图像进行滤波处理,以增强图像中的亮度信息。通过使用Retinex增强算法,我们可以有效地提高图像的质量,增强图像中的细节和颜色信息。最后,Retinex算法通过将颜色恢复和亮度调整后的图像进行比例调整,以获得最终的增强图像。Retinex算法是一种常用的图像增强算法,它通过对图像的亮度和颜色进行调整,以提高图像的视觉质量。

XsiJava的博客 435

JAVA高级面试总结-基础篇

JAVA高级面试总结-基础篇

初心不改,事在人为 286

xilinx原语及bank简介

图8是HP bank与HR bank的IO模块,其中PAD是FPGA的金属管脚,IOB是输入、输出引脚的控制模块。此时使用原语就可以只调用需要的组件,不需要去考虑其余组件参数设置,就方便很多,借助此次机会就对IDDR、ODDR、IDELAYE2、ODELAYE2、IDELAYCRTL、ISERDESE、OSERDESE等几个原语做了简要了解,并对原语的各个模式进行了仿真,本文最初是介绍IDDR的,但在介绍IDDR这些原语之前,还需要了解一下7系列FPGA bank的分类和区别,所以就有了本文。

qq_43416206的博客 412

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

java——《面试题——基础篇》

1、Java语言有哪些特点1、简单易学、有丰富的类库2、面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高)3、与平台无关性(JVM是Java跨平台使用的根本)4、可靠安全5、支持多线程。

行秋的博客 9849

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Java语言程序设计(基础篇)课后答案

免责申明:上传资料仅供学习交流使用,禁止一切不正当使用行为,如有事故本人概不负责 Java语言程序设计(基础篇)课后习题配套答案,仅1-12章偶数题,这是此书的配套答案。 http://download.youkuaiyun.com/detail/xunciy/9887093 Java语言程序设计(基础篇)1-11章课后44条代表性习题答案,这是我自己的写的程序,包括五子棋、八皇后、豆机等在内的简易小游...

Sophia_fez的博客 2万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java面试通关要点汇总集(基础篇+核心篇+框架篇+微服务篇)

基础篇 基本功 面向对象的特征 final, finally, finalize 的区别 int 和 Integer 有什么区别 重载和重写的区别 抽象类和接口有什么区别 说说反射的用途及实现 说说自定义注解的场景及实现 HTTP 请求的 GET 与 POST 方式的区别 session 与 cookie 区别 session 分布式处理 JDBC 流程 MVC 设计思想 equals 与 == 的区别 集合 List 和 Set 区别 List 和 Map 区别 A.

如果频繁就私信一下呢 296

Java学习之基础篇

Java学习之基础篇 为了更形象的将知识点进行总结,我基本给每个知识点都附上了源代码,通过代码的运行来加深对知识点的掌握 1.使用IDEA编写代码 · 新建src文件夹新建java类 · 快捷指令psvm、sout public class base1 { public static void main(String[] args) {//快捷键psvm(适用于IDEA) System.out.println();//快捷键sout(适用于IDEA) } } 2.什么是字节

gao1518609759的博客 309

JAVA学习基础篇

JAVA学习基础篇前言一、变量的使用二、数据类型(基本数据类型、引用数据类型)三、 修饰符1、访问控制修饰符2、非访问控制修饰符 前言 作为一个代码小白,真的只有慢慢的进阶了,我真的学的超级慢!但是还是会持续更新的!现在开始学习的是java,java的使用频率很高,小伙伴们可以关注 https://www.tiobe.com/tiobe-index/ 这个网站查看语言的增减情况和使用比例,超级好用!!!想当马卡农的都用起来!!!(下面是展示) 什么语言都离不开最基本的东西(变量使用、数据类型等)有了

qq_45934578的博客 276

JAVA语言程序设计(基础篇)第十版

Java语言程序设计基础篇 https://pan.baidu.com/s/1mhNRCfQ

summerdream_的博客 7386

Java八股文——Java基础篇

本文详细收集了Java八股文面试中常见的24个经典问题,并给出了详细的解答方案。

郎逸的博客 2151

基础篇-Java基础加强

基础篇-Java基础加强 01 | 导读 1、测试分类:白盒测试和黑盒测试 2、Java代码的三个阶段:Source源代码阶段、Class类对象阶段、Runtime运行时阶段 02 | Junit单元测试 1、测试分类 1)黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。 2)白盒测试:需要写代码的。关注程序具体的执行流程。 2、Junit使用:白盒测试步骤 1、定义一个测试类(测试用例) 测试类名:被测试的类名Test CalculatorTest 包名:xxx.xxx.xx.t

z_z_z_666666的博客 286

零基础入门Java·基础篇 学习大纲

本文为零基础入门Java的基础篇学习大纲,按照“前置认知→环境搭建→语法基础→核心结构→实战巩固”的循序渐进逻辑规划,覆盖Java入门必备的核心章节。每个章节对应一篇详细博客,发布后会在“博客发布链接”列补充直达链接,方便大家按纲学习、逐个突破,轻松开启Java编程之旅。

CharlesYuangc的博客 206

《Java语言程序设计基础篇 第12版》第一章部分习题

文章仅用于记录笔者学习过程,下面案例仅供参考。

Coconutlover的博客 1750
上一篇: [Java虚拟机]Java内存模型与线程
下一篇: [Android开发]知乎日报
陶程
博客等级 码龄12年 360粉丝 56原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值