java知识点总结

最近在面试,笔试时,问到的一些题目,自己回答的时候都有些不全面,故总结如下,不断更新中~

目录

一、jdbc过程

二、socket原理

三、java调用对象的几种方法

四、hashcode的实现机制

五、接口的分类


 

一、jdbc过程

首先,需要知道使用Java开发任何数据库应用程序都需要4个主要接口:Driver,Connection,Statement和ResultSet。这些接口定义了使用SQL访问数据库的一般架构。访问数据库的Java程序主要有5个步骤,分别是:

1)加载驱动程序。

2)建立连接。

3)创建语句。

4)执行语句。

5)处理ResultSet。

那么就简单说明这5个步骤如何实现:

1)加载驱动程序

在连接到数据库之前,需要加载一个合适的驱动程序。

Class.forname("com.mysql.cj.jdbc.Driver");

驱动程序是一个实现接口java.sql.Driver的具体类。因为我用的数据库是MySQL,所以在括号里填com.mysql.cj.jdbc.Driver,像其他的数据库,会有不同的程序驱动类。

2)建立连接

连接到数据库需要使用到DriverManager类中的静态方法getConnection(databaseURL),其中databaseURL是数据库在Internet上的唯一标识符。

Connection connection=DriverManager.getConnection("jdbc:mysql://localhost/Contacts?serverTimezone=UTC", "root", "Cc229654512");

3)创建语句

Statement的对象可以为数据库传输SQL语句用于执行,并把运行结果返回程序。一旦创建Connection对象,就可以创建执行SQL语句的语句。

Statement statement=connection.createStatement();

4)执行语句

可以使用方法executeUpdate(String sql)来执行数据定义语言或者更新语句,可以使用executeQuery(String sql)来执行SQL查询语句。结果在ResultSet中返回。

ResultSet resultSet=statement.executeQuery("select Name, PhoneNumber, Email, QQ, Note from Contacts");

5)处理ResultSet

结果集ResultSet可以获得表的当前行,可以使用next方法移动行,可以使用各种get方法获取当前行的值。

while(resultSet.next())

{
        System.out.println(resultSet.getString(1)+"\t"+resultSet.getString(2)+"\t"+resultSet.getString(3));
}

 

二、socket原理

Socket是什么呢?

       Socket是应用层与TCP/IP协议族(运输层)通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。是“open—write/read—close”模式的一种实现

过程:

java知识点总结_第1张图片

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

 

三、java调用对象的几种方法

1. 用new语句创建对象,这是最常见的创建对象的方法。

2 还有就是这种,通过工厂方法返回对象

String emp0 = String.valueOf(23); 

String emp1 = "123";

3 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。

CreateInstance instance = (CreateInstance)Class.forname("com.create.instance.CreateInstance").newInstance();

Employee emp2 = Employee.class.newInstance()

4 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

objectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp4 = (Employee) in.readObject();


5 clone()克隆方法。 
Employee emp5 = (Employee) emp3.clone();

 

四、hashcode的实现机制

1 为什么使用 hashcode

hashCode 存在的第一重要的原因就是在 HashMap中使用,HashMap 之所以速度快,因为他使用的是散列表,根据 key 的 hashcode 值生成数组下标(通过内存地址直接查找,没有任何判断),时间复杂度完美情况下可以达到 n1(和数组相同,但是比数组用着爽多了,但是需要多出很多内存,相当于以空间换时间)。

2 重写hashcode

使用 String 的 char 数组的数字每次乘以 31 再叠加最后返回,因此,每个不同的字符串,返回的 hashCode 肯定不一样。

3 为什么乘以31

之所以使用 31, 是因为他是一个奇素数。如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算(低位补0)。使用素数的好处并不很明显,但是习惯上使用素数来计算散列结果。 31 有个很好的性能,即用移位和减法来代替乘法,可以得到更好的性能: 31 * i == (i << 5) - i, 现代的 VM 可以自动完成这种优化。这个公式可以很简单的推导出来。

 

五、接口的分类

1 单方法接口
以下是引用片段:
[2] public interface Actionlistener{
public abstract void actionPerformed(ActionEvent event);
}
仅且只有一个方法,只有实现了这个接口(重写这个接口中的唯一一个方法),你才有资格去事件监听器列表里注册(参数为Actionlistener类型),当事件源变动时,自动调用这个唯一的actionPerformed方法。
2 标识接口
是没有任何方法和属性的接口。标识接口不对实现它的类有任何语意上的要求,它仅仅表明了实现它的类属于一个特定的类型(传递)。
不推荐过多的使用标识接口。
3 常量接口
用Java接口来声明一些常量,然后由实现这个接口的类使用这些常量(以前在做画板的时候这么干过)。建议不要模仿这种常量接口的做法。

六、Java虚拟机

内容太长,单独开贴

https://blog.csdn.net/qq_27667379/article/details/81624700

七、java内存泄漏的原因及分析

定义:内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。

会发生的场景:

1、静态集合类引起内存泄露:

像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。

例:

Static Vector v = new Vector(10);

for (int i = 1; i<100; i++){

Object o = new Object();

v.add(o);

o = null;}//

在这个例子中,循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身(o=null),那么Vector 仍然引用该对象,所以这个对象对GC 来说是不可回收的。因此,如果对象加入到Vector 后,还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null。

2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。

例:

public static void main(String[] args){

Set set = new HashSet();

Person p1 = new Person("唐僧","pwd1",25);

Person p2 = new Person("孙悟空","pwd2",26);

Person p3 = new Person("猪八戒","pwd3",27);

set.add(p1);

set.add(p2);

set.add(p3);

System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:3 个元素!

p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变

set.remove(p3); //此时remove不掉,造成内存泄漏

set.add(p3); //重新添加,居然添加成功

System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素!

for (Person person : set){

System.out.println(person);}}

3、监听器

在java 编程中,我们都需要和监听器打交道,通常一个应用当中会用到很多监听器,我们会调用一个控件的诸如addXXXListener()等方法来增加监听器,但往往在释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会。

4、各种连接

比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。对于Resultset 和Statement 对象可以不进行显式回收,但Connection 一定要显式回收,因为Connection 在任何时候都无法自动回收,而Connection一旦回收,Resultset 和Statement 对象就会立即为NULL。但是如果使用连接池,情况就不一样了,除了要显式地关闭连接,还必须显式地关闭Resultset Statement 对象(关闭其中一个,另外一个也会关闭),否则就会造成大量的Statement 对象无法释放,从而引起内存泄漏。这种情况下一般都会在try里面去的连接,在finally里面释放连接。

5、内部类和外部模块等的引用

内部类的引用是比较容易遗忘的一种,而且一旦没释放可能导致一系列的后继类对象没有释放。此外程序员还要小心外部模块不经意的引用,例如程序员A 负责A 模块,调用了B 模块的一个方法如:

public void registerMsg(Object b);

这种调用就要非常小心了,传入了一个对象,很可能模块B就保持了对该对象的引用,这时候就需要注意模块B 是否提供相应的操作去除引用。

6、单例模式

不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:

class A{

public A(){

B.getInstance().setA(this);}....}

//B类采用单例模式

class B{

private A a;

private static B instance=new B();

public B(){}

public static B getInstance(){

return instance;}

public void setA(A a){

this.a=a;}

//getter...}

显然B采用singleton模式,它持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较复杂的对象或者集合类型会发生什么情况

你可能感兴趣的:(java知识点)