明天就要面试了,零时抱一下佛脚------Java基础

面向对象编程(OOP)

  • 类与对象

  • 类与对象是面向对象编程的核心思想
  • 类是对象的抽象,对象是类的实例
  • 例如人类有姓名、身高、体重等特征,而张三是人类的一个实例
  • 封装

  • 封装是指隐藏类的属性和方法,只通过必要的方法暴露接口
  • 说白了就是将方法的属性设置为private,以防止属性被非法访问和修改
  • 继承

  • 继承是指子类继承现有的父类
  • 继承后的子类可以共享父类的属性和方法
  • 在Java中一个子类只能继承一个父类,而一个类可以由多个子类继承(一个儿子只能有一个爸爸,而一个爸爸可以有多个儿子)
  • 多态

  • 多态是指实体类具有多种形态,多态主要体现形式有重载和重写
  • 重载是指方法名相同,而参数的类型或者参数的个数不同
  • 重写是指子类继承父类后重新改写了父类方法的方法体,虽然方法名和父类相同,但是内部实现操作不同

集合框架 

  • 有序集合List,如ArrayList和LinkedList

  • list集合是有序的,允许元素重复,每个元素都有对应的下标索引,
  • ArrayList:基于动态数组实现的,支持快速随机访问。当你需要频繁访问列表中的元素时,ArrayList是一个很好的选择。但不适合频繁的插入和删除。
  • LinkedList:基于双向链表实现的,适合于插入和删除操作,特别是当你需要在列表的开头或中间频繁进行这些操作时。但是,由于链表的随机访问速度较慢,如果你需要频繁访问元素,LinkedList可能不是最佳选择。
  • list操作方法:
add(E e):在列表末尾添加一个元素,返回true。
add(int index, E element):在指定位置插入一个元素。
get(int index):返回指定位置的元素。
set(int index, E element):替换指定位置的元素,并返回被替换的元素。
remove(Object o):从列表中删除指定元素,删除成功返回true。
remove(int index):删除指定位置的元素,并返回被删除的元素。
size():返回列表中的元素数量。
isEmpty():检查列表是否为空,为空则返回true。
clear():清空列表中的所有元素。
indexOf(Object o):返回对象在列表中第一次出现的索引。
lastIndexOf(Object o):返回对象在列表中最后一次出现的索引。
  • 无序集合Set,如HashSet和TreeSet

  • set集合不包含重复元素,没有顺序,主要用于保证元素唯一性,
  • HashSet:基于哈希表实现的,它不保证元素的顺序,但提供快速的插入、删除和查找操作。HashSet在内部使用哈希函数将元素分布到不同的桶中,这使得大多数操作的时间复杂度为O(1)。
  • TreeSet:基于红黑树实现的,它不仅确保元素的唯一性,还维护元素的排序(自然排序或根据提供的比较器定制排序)。TreeSet适合于需要有序元素的场景,但与HashSet相比,它的操作速度稍慢,因为需要维护树的平衡。
  • list操作方法:
  • add(E e):向集合中添加元素,若添加成功返回true。
    remove(Object o):从集合中删除元素,若删除成功返回true。
    contains(Object o):检查集合是否包含指定元素,包含则返回true。
    size():返回集合中的元素数量。
    isEmpty():检查集合是否为空,为空则返回true。
    clear():清空集合中的所有元素。
    iterator():返回集合的迭代器,用于遍历集合。
  • 键值对集合Map,如HashMap和TreeMap。 

  • Map集合是键值对集合,其中键是唯一的不可重复的,提供键到值的映射,
  • HashMap:基于哈希表实现的,它允许空键和空值。HashMap不保证元素的顺序,提供快速的插入、删除和查找操作。与HashSet类似,HashMap在内部使用哈希函数将键分布到不同的桶中,大多数操作的时间复杂度为O(1)。
  • TreeMap:基于红黑树实现的,它不仅确保键的唯一性,还维护键的排序(自然排序或根据提供的比较器定制排序)。TreeMap适合于需要有序键的场景,但与HashMap相比,它的操作速度稍慢,因为需要维护树的平衡。
  • Map操作方法:
put(K key, V value):将指定的值与此映射中的指定键关联,返回先前的值。
get(Object key):返回指定键所映射的值。
remove(Object key):如果存在一个键的映射关系,则将其从映射中移除。
keySet():返回映射中包含的键的Set集合。
values():返回映射中包含的值的Collection视图。
entrySet():返回映射中包含的键值映射关系的Set集合。
size():返回映射中的键-值映射关系的数量。
isEmpty():检查映射是否为空,为空则返回true。
clear():清空映射中的所有键值映射关系。

多线程和并发 

多线程

  •  线程(Thread):线程是程序中最小的执行单元,可以同时运行多个线程以提高效率
  • 创建线程:
    1. 通过继承Thread类创建线程,
      // 继承Thread类
      class MyThread extends Thread {
          @Override
          public void run() {
              System.out.println("线程运行中:" + Thread.currentThread().getName());
          }
      }
      
      // 在主类中创建并启动线程
      public class ThreadExample {
          public static void main(String[] args) {
              MyThread myThread = new MyThread(); // 创建线程
              myThread.start(); // 启动线程
          }
      }
    2. 或者实现Runnable接口来创建线程
//通过实现Runnable接口创建线程

// 实现Runnable接口
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程运行中:" + Thread.currentThread().getName());
    }
}

// 在主类中创建并启动线程
public class RunnableExample {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable(); // 创建Runnable实例
        Thread thread = new Thread(myRunnable); // 将Runnable实例传给Thread
        thread.start(); // 启动线程
    }
}

  • 同步(Synchronized):确保多个线程访问共享资源时,一次只有一个线程进行操作,避免数据的不一致
  • 应用:用synchronized关键字修饰方法或代码块,确保线程安全。
class Account {
    private int balance;

    public Account(int balance) {
        this.balance = balance;
    }

    // 使用synchronized修饰方法
    public synchronized void deposit(int amount) {
        balance += amount;
        System.out.println("存款后余额:" + balance);
    }
}

class AccountThread extends Thread {
    private Account account;

    public AccountThread(Account account) {
        this.account = account;
    }

    @Override
    public void run() {
        account.deposit(100);
    }
}

public class SynchronizedExample {
    public static void main(String[] args) {
        Account account = new Account(0);

        // 创建并启动两个线程
        Thread thread1 = new AccountThread(account);
        Thread thread2 = new AccountThread(account);

        thread1.start();
        thread2.start();
    }
}

  • 锁(lock):提供了比synchronized更灵活的线程同步控制。可以通过Lock接口实现更复杂的同步策略,如尝试非阻塞获取锁、可中断的锁获取等。 
  • 使用ReentrantLock实现锁:

    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class Account {
        private int balance;
        private final Lock lock = new ReentrantLock(); // 创建一个ReentrantLock对象作为锁
    
        public Account(int balance) {
            this.balance = balance;
        }
    
        // 使用Lock实现存款方法
        public void deposit(int amount) {
            lock.lock(); // 获取锁
            try {
                balance += amount;
                System.out.println("存款后余额:" + balance);
            } finally {
                lock.unlock(); // 释放锁
            }
        }
    }
    
    class AccountThread extends Thread {
        private Account account;
    
        public AccountThread(Account account) {
            this.account = account;
        }
    
        @Override
        public void run() {
            account.deposit(100);
        }
    }
    
    public class LockExample {
        public static void main(String[] args) {
            Account account = new Account(0);
    
            // 创建并启动两个线程
            Thread thread1 = new AccountThread(account);
            Thread thread2 = new AccountThread(account);
    
            thread1.start();
            thread2.start();
        }
    }

上述案例使用了ReentrantLock来替代synchronized关键字。ReentrantLock提供了比synchronized更灵活的锁定机制,例如:

  • 尝试获取锁(tryLock):可以非阻塞地尝试获取锁,如果锁不可用,线程可以不做等待继续执行其他任务。

  • 可中断的锁获取(lockInterruptibly):在等待锁的过程中,如果线程被中断,可以响应中断,而不是无限期地等待锁。

  • 公平锁(Fair Lock):可以选择创建公平锁,使得等待时间最长的线程优先获取锁。


并发集合

  • 并发集合:并发集合是指Java集合框架中专门为多线程环境设计的集合,它们内部已经处理好了线程安全问题,使得在多线程访问时不需要额外的同步措施,如ConcurrentHashMap。这些集合类位于java.util.concurrent包中。

ConcurrentHashMap是并发集合中的一个,它是一个线程安全的哈希表。与Hashtable不同,Hashtable在每次访问时都需要对整个结构加锁,而ConcurrentHashMap采用了一种细粒度的锁定机制,这意味着在进行读操作时通常不需要加锁,而在写操作时只锁定相关的一部分,从而提供了更好的并发性能。

特点:

  • 线程安全:ConcurrentHashMap内部通过分段锁(segmentation)或CAS(Compare-And-Swap)操作来保证线程安全,无需外部同步。

  • 高性能:由于锁的粒度更细,ConcurrentHashMap在读操作密集或写操作较少的场景下,性能通常优于Hashtable

  • 动态扩容:ConcurrentHashMap在需要时可以动态地进行扩容,而不需要重新构建整个哈希表。

  • 支持并发操作:ConcurrentHashMap允许多个线程同时进行操作,而不会产生冲突。

使用场景:

  • 当你需要一个线程安全的哈希表,并且希望在高并发环境下保持良好的性能时,ConcurrentHashMap是一个理想的选择。

  • import java.util.concurrent.ConcurrentHashMap;
    
    public class ConcurrentHashMapExample {
        public static void main(String[] args) {
            ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
    
            // 并发地对map进行操作
            map.put("one", 1);
            map.put("two", 2);
            map.put("three", 3);
    
            // 并发读取
            System.out.println(map.get("two")); // 输出 2
        }
    }

JVM(Java虚拟机) 

类加载机制

  • 加载(Loading):JVM通过全限定名查找.class文件,加载类的数据到方法区。

  • 链接(Linking):将类的二进制数据合并到JVM中,包括验证、准备(为静态变量分配内存)和解析(将符号引用替换为直接引用)。

  • 初始化(Initialization):执行类构造器<clinit>()方法,初始化静态变量。

加载、链接、初始化,是类生命周期的三个阶段

内存模型

  • 堆(Heap):存放对象实例和数组,所有线程共享,垃圾回收主要在此区域进行。

  • 栈(Stack):每个线程私有,存放局部变量和方法调用信息,方法执行完毕后自动释放。

  • 方法区(Method Area):存放类信息、常量和静态变量,所有线程共享。

堆、栈、方法区,是JVM内存的三大区域。

垃圾回收 

  • 标记-清除(Mark-Sweep):标记可回收对象,然后清除,但可能产生内存碎片。

  • 复制(Copying):将内存分为两半,每次只使用一半,用完复制存活对象到另一半,然后清理。

  • 标记-整理(Mark-Compact):先标记可回收对象,然后将存活对象向一端移动,紧凑排列。

  • 分代收集(Generational Collection):根据对象生命周期分为新生代和老年代,新生代使用复制算法,老年代使用标记-清除或标记-整理。

标记-清除、复制、标记-整理,是垃圾回收的三种基本算法。

性能调优 

  • 参数调整:通过调整JVM启动参数(如堆大小、垃圾回收器选择)来优化性能。

  • 监控工具:使用JVM监控工具(如JConsole、VisualVM)来分析应用性能,找出瓶颈。

参数调整和监控工具,是优化JVM性能的两大手段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值