1.抽象类为什么不能创建对象?
1.子类更具体,父类更抽象,直接创建父类对象本身没有意义。
2.如果创建的是父类对象,在调用方法的时候,调用的父类中的方法而并非子类的方法,他违背了多态的设计思想。
3.因为父类引用指向子类对象时,调用的方法是子类重写的方法,并不是说抽象类的构造方法没有意义,那么在创建子类对象时需要先调用父类的构造方法。
(1)抽象类的定义:
抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。通常在编译语句中用abstract修饰的类是抽象类。在c++中,含有纯虚拟函数的类称为抽象类,它不能创建对象;在java中,含有抽象方法的类称为抽象类,它同样也不能创建对象。
(2)抽象方法(由子类具体实现)
java中的抽象方法就是以abstract修饰的方法,这种方法只声明返回的数据类型,方法名称和所需的参数,没有返回方法体,也就是抽象方法只需要声明而不需要实现。抽象方法不能被调用。
(3)抽象类为什么不能创建对象?
首先,与具体的类进行比较:抽象类不能实例化,并且不能使用new创建对象(如果使用,会导致编译时错误)。虽然一些变量和值在编译时的类型可以为抽象的,但是,这些变量和值必须为null,或者说含有对非抽象类的实例的引用(此非抽象类是从抽象类派生出来的),允许抽象类包含抽象成员。
其次,与接口进行比较:
相同点:(1)抽象类和接口都不能直接实例化(创建对象);
(2)抽象类的子类(或接口的实现类),都必须实现抽象类(或接口)中全部的抽象方法,才可以被实例化,否 则,该类仍然为抽象类
不同点:(1)关键字不同,抽象类子类使用extends关键字实现抽象类;接口实现是使用关键字implements来实现接口
(2)抽象类中可以有构造方法;接口中不能有构造方法
(3)抽象类中既可以有抽象方法也可以有普通方法;接口中只能有抽象方法
(4)权限修饰不同:抽象方法可以有public,protected和default这些修饰符;接口方法只能是public
(5)抽象类中的变量可以是普通变量;接口中定义的变量只能是公共的静态变量
(6)抽象方法可以继承单个类和实现多个接口;接口可以多继承接口
(7)速度:抽象类比接口的速度要快,接口稍微有点慢,需要时间去寻找在类中实现的方法
补充::
注意:
(1)一个类中如果有抽象方法,那么这个类只能是抽象类
(2)抽象方法要被实现,所以不能是静态的,也不能是私有的
(3)接口中只能含有未被实现的方法,也叫抽象方法;但是不能用abstract关键字修饰
抽象类的使用原则:
(1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
(2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
(3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
(4)子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。);抽象类是不能定义对象的。一个纯虚函数不需要(但是可以)被定义。
2.SQL查询语句关键字的执行顺序
Mysql语法顺序:
- select[distinct]
- from
- join(如left join)
- on
- where
- group by
- having
- union
- order by
- limit
Mysql执行顺序
- from
- on
- join
- where
- group by
- having
- select
- distinct
- union
- order by
3.Statement和PreparedStatement的区别
(1)什么是Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句。
(2)Statement对象用于将SQL语句发送到数据库中,用于执行静态 SQL 语句并返回它所生成结果的对象。
实际上有Statement有三种对象,Statement它们都作为在给定连接上执行SQL语句的包容器:
Statement,PreparedStatement(它是由Statement上继承来的),CallableStatement(它从PreparedStatement继承来的)。
它们都专用于发送特定类型的SQL语句:
- Statement对象用于执行不带参数的简单SQL语句;
- PreparedStatement对象用于执行带或不带参数的预编译的SQL语句;
- CallableStatement对象用于执行对数据库已存储过程的调用。
(3)PreparedStatement: 表示预编译的 SQL 语句的对象,SQL 语句被预编译并存储在 PreparedStatement 对象中。
数据库会对sql语句进行预编译,下次执行相同的sql语句时,数据库端不会再进行预编译了,而直接用数据库的缓冲区,提高数据访问的效率(但尽量采用使用?号的方式传递参数),如果sql语句只执行一次,以后不再复用。 从安全性上来看,PreparedStatement是通过?来传递参数的,避免了因sql而出现sql注入的问题,所以安全性较好。 在开发中,推荐使用 PreparedStatement
优劣比较:
Statement每次执行sql语句,数据库都要执行sql语句的编译,最好用于仅执行一次查询并返回结果的情形,效率高于 PreparedStatement.但存在sql注入风险。
PreparedStatement是预编译执行的。在执行可变参数的一条SQL时,PreparedStatement要比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率高。安全性更好,有效防止SQL注入的问题;有更好的可读性和可维护性;对于多次重复执行的语句,使用PreparedStatement效率会更高一点。
4.lock 和 synchronized
- synchronized 是 Java 关键字,内置特性;Lock 是一个接口
- synchronized 会自动释放锁;lock 需要手动释放,所以需要写到 try catch 块中并在 finally 中释放锁
- synchronized 无法中断等待锁;lock 可以中断
- Lock 可以提高多个线程进行读/写操作的效率
- 竞争资源激烈时,lock 的性能会明显的优于 synchronized
可重入锁
- 定义:已经获取到锁后,再次调用同步代码块/尝试获取锁时不必重新去申请锁,可以直接执行相关代码
- ReentrantLock 和 synchronized 都是可重入锁
公平锁
- 定义:等待时间最久的线程会优先获得锁
- 非公平锁无法保证哪个线程获取到锁,synchronized 就是非公平锁
- ReentrantLock 默认时非公平锁,可以设置为公平锁
乐观锁和悲观锁
乐观锁与悲观锁是逻辑上的锁。
乐观锁:
- 乐观锁:乐观地认为,并发问题很难发生。
- 乐观锁虽然认为并发问题很难发生,但并不是不会发生,所以也会有措施防止问题真的产生:每次数据修改都自增版本号version。
- 进行数据读取时,并不加锁,而是同时读取当前的版本号version1;在对数据进行修改时,要判断当前的版本号version2是否等于之前的版本号version1。
- 版本号不匹配,则代表着并发问题已产生,所以需要回滚此次操作。
- 实现方式:版本号机制、CAS。Compare And Swap,更新数据时先比较原值是否相等,不相等则表示数据过去,不进行数据更新
悲观锁:
- 悲观锁:悲观地认为,并发问题极易发生。synchronized 就是悲观锁
- 悲观锁认为并发问题极易发生,所以每次操作,无论读写,都会对记录加锁,以防止其他线程对数据进行修改。
- 实现方式:数据库的行锁、读锁和写锁。
行级锁和表级锁
行级锁
- ow-level loking,锁住一行记录。
- 开销大,加锁慢。
- 会死锁。
- 锁粒度小,发生所冲突概率小,并发效率高。
- 适合并发写,事务控制。
- 并不是直接丢记录行加锁,而是对行对应的索引加锁:
如果sql 语句操作了主键索引,Mysql 就会锁定这条主键索引。
如果sql语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。
在InnoDB中,如果SQL语句不涉及索引,则会通过隐藏的聚簇索引来对记录加锁。
对聚簇索引加锁,实际效果跟表锁一样,因为找到某一条记录就得扫描全表,要扫描全表,就得锁定表。表级锁
- table-level locking,锁住整个表。
- 开销小,加锁快。
- 不会死锁(一次性加载所需的所有表)。
- 锁粒度大,发生锁冲突概率大,并发效率低。
- 适合查询。
共享锁与排他锁
共享锁:
- 有称之为S锁、读锁。
- 当前线程对共享资源加共享锁,其他线程可以读取此资源、可以继续追加共享锁,但是不能修改此资源、不能追加排他锁。
- 语法:select id from t_table in share mode;
- 多个共享锁可以共存,共享锁与排他锁不能共存。
排他锁:
- 又称之为X锁、写锁。
- 当前线程对共享资源加排他锁,其他线程不允许读取此资源,不允许追加共享锁,不允许修改此资源,不允许追加排他锁。
语法:
update t_table set a =1; // 数据库的增删改操作默认都会加排他锁
select * from t_table for update;// for update也是一种增删改
- 排他锁是独占的,不会与其他锁共存。