Java基础

2019/12/10

4种访问修饰符

访问权限 子类 其他包
public
protect ×
default × ×
private × × ×

数据库视图

一个表或多个表导出的虚拟的表,其内容由查询定义。具有普遍的表结构,但不能实现数据存储

我们在使用查询时,在很多时候我们要使用聚合函数,同时还要 显示其它字段的信息,可能还会需要关联到其它表,这时写的语句可能会很长,如果这个动作频繁发生的话,我们可以创建视图

优点:简化操作 安全 ,只能查到规定的数据*

存储过程

完成特定功能的SQL 语句集

sql语句先编译再执行的;而存储过程是已经编译好的代码,所以被调用或引用时,执行效率非常高。

使用:较复杂的数据库批处理的项目 代码量 ,效率 可维护性都比程序组装sql 好用

推荐不使用:

mysql使用率提高(存储过程比较弱)。只是现在行业环境不一样了,即便互联网盛行的情况下随便拉出来一个银行系统,都有很多的存储过程。因为缓存越来越成熟,所以会选择使用缓存去取代存储过程。

DB本身就是存储数据的,如果要把业务强行放进去,未免有些搞笑。

互联网公司 分表分库 需求变动比较频繁 ,性能瓶颈的时候能加服务器比数据库容易

创建存储过程的语法结构:

CREATE [OR REPLACE] procedure pro_name  [(parameter1[,parameter2]...] is|as
begin
  ``plsql_sentences;
[exception]
  ``[dowith_sentences;]
end [pro_name];

–>pro_name:存储过程的名称,如果数据库中已经存在了此名称,则可以指定”OR PLACE”关键字来覆盖原来的存储过程;如果不想覆盖,可修改名称,这样就可以区分开了

–>parameter1: 存储过程被调用或执行时用到的参数。【注意:这个值不是存储过程内定义的内部变量,内部变量应该在is|as之后定义】

parameter1如果是输入参数,则需要在后面指定IN关键字;如果是输出参数,则需要在后面指定OUT关键字,在IN和OUT后面加的是参数的数据类型,不需要指定长度;【不明白不要紧,后面会举例说明;】

–>plsql_sentences:PL/SQL语句,存储过程中功能实现的主要代码

–>dowith_sentences:异常处理语句,是可选的PL/SQL语句(不需要可以不写

Oracle中如何写存储过程

SOA和微服务架构

SOA面向服务的框架。

微服务是SOA的进一步发展,服务根据业务拆分。

序列化和反序列化

序列化   由于存在于内存中的对象都是暂时的,无法长期驻存,为了把对象的状态保持下来,这时需要把对象写入到磁盘或者其他介质中,这个过程就叫做序列化。

反序列化   反序列化恰恰是序列化的反向操作,也就是说,把已存在在磁盘或者其他介质中的对象,反序列化(读取)到内存中,以便后续操作,而这个过程就叫做反序列化。

  • 序列化的应用情景

  主要有以下情况(但不限于以下情况)

  • 1)内存中的对象写入到硬盘;
  • 2)用套接字在网络上传送对象;
  • 3)通过RMI(Remote Method Invoke 远程方法调用)传输对象

对于超过3层的 if-else 的逻辑判断代码,可以使用卫语句、策略模式、状态模式等来实现

什么是函数式接口

所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法。

/**
 * 真正的业务处理
 */
@FunctionalInterface
public static interface RequestExecutor {
    Object doExecute() throws BusinessException;
}

/**
 * 请求模板
 */
public void templateRequest(RequestExecutor executor) {
    // 获取response对象
    HttpServletResponse response =
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    
    try {
        
        Object result = executor.doExecute();
        writeAjaxJSONResponse(ResultMessageBuilder.build(true, "success!", result), response);
        
    } catch (Exception e) {
    
        logger.error("请求失败", e);
        writeAjaxJSONResponse(ResultMessageBuilder.build(false, 500, "系统异常"), response);
        
    }
}

/**
 * controller部分代码
 */
@PostMapping(path = "/pageQuery")
public void pageQuery(@RequestBody Query query) {
    templateRequest(() -> service.pageQuery(query));
}

/**
 * service部分代码
 */
public PagedResult<VO> pageQuery(Query query);

用于某一特定的场景,但是有不同的处理逻辑的时候,比如导入数据,导入是共性,但是处理逻辑都不同

lambda表达式如何序列化

查看hashmap的源码

public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
    return (Comparator<Map.Entry<K, V>> & Serializable)
        (c1, c2) -> c1.getValue().compareTo(c2.getValue());
}

序列化对象是需要有实现序列化接口的。但Comparator并没有实现

我们知道&按位与操作,但是两个数据类型按位与?没见过? 实际上,这是强制类型转换,转换成可序列化的Comparator<Map.Entry<K, V>>对象&的意思是且的意思。

这种强制类型转换可以将一个对象直接转换为Serializable对象。

泛型

解决不确定具体数据类型的问题

早期Java是使用Object来代表任意类型的,但是向下转型有强转的问题,这样程序就不太安全

生成字节码文件 会泛型擦除

<T extends Comparable<? super T>>

元素必须是实现了Comparable接口的类或者其子类,可以使用父类方法比较子类型

<T extends Comparable<? super T»

那些字段需要transient修饰

1.类中的字段 可以 根据其它字段 推导出来 主要为了节省存储空间

2.看业务需求,哪些字段不想被序列化

  1. 不同程序 导致值不同

  2. ==ObjectOutputStream:通过 writeObject()方法做序列化操作== 
  3. ==ObjectInputStream:通过 readObject() 方法做反序列化操作==

transient

Object.hashCode是nativate 不同的JVM里可能不一样

fail-fast机制

集合中常见的错误机制,通常出现在遍历集合元素过程中。

简单说就是优先考虑异常,发现异常直接停止上报。

提到java集合类中fail-fast机制,大概就是抛出ConcurrentModificationException这个异常了。 这里拿ArrayList的iterator()的源码说明一下

1、迭代器iterator()方法执行的时候int expectedModCount = modCount,
2、modCount是AbstractList定义的 protected transient int modCount = 0;
3、迭代器在调用 next()、remove() 方法时都是调用 checkForComodification() 方法,
该方法主要就是检测 modCount == expectedModCount ?
4、ArrayList 中无论 add、remove、clear 方法只要是涉及了改变 ArrayList 元素的个数的方法都会导致 modCount 的改变

部分源码

 public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;//调用iterator()的时候赋值

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

fail-safe解决之道

java.util.concurrent包下的容器都是fail-safe 对应ArrayList的类CopyOnWriteArrayList CopyOnWriteArrayList这个类设计思想是读写分离,写(add/remove)操作是copy一份副本,在这个副本里操作完成之后再用这个副本替换原件。 当然为了避免出现多个副本,写操作是需要加锁的。这个类适用于读多写特别少的情况,否则很容易OOM。

Copy-On-Write COW奶牛家族

第一:尽量设置合理的容量初始值,他扩容的代价很大、

第二:适合读多写极少的情况

ArrayList

ArrayList底层实现是数组。

当使用无参数构造函数创建ArrayList对象时,ArrayList对象中的数组初始长度为0(是一个空数组)。

ArrayList的扩容策略是每次都增加当前数组长度的一半(非固定分配)。

ArrayList的扩容方式是直接创建一个新的数组,并将数据拷贝到新数组中

面试官最爱的volatile关键字

1 . 保证了不同线程对该变量操作的内存可见性;

2 . 禁止指令重排序

Post Directory