2021/1/14 牛客百题总结

唉,每次做题花的时间并不算太多,大概三十题也就二十多分钟,但要将这三十题做成总结就最少需要一个小时,感觉效率有些低。
刷过400题后,现在错误的大多不是非常大的知识点了,是对一些细节方面处理不到位,因此,可能以后会二百题一总结,并且对前面的知识点进行巩固,现在基本上只是有了一个大体的印象。

1.数据库连接的基本操作

//声明数据库驱动,数据源的url,用于登录数据库的账户和密码(将其他功能封装成方法的时候方便使用)
String driver = "数据库驱动名称";
String url = "数据库连接地址"
String user = "用来连接数据库的用户名";
String pwd = "用来连接数据库的密码"//加载数据库驱动  
Class.forName(driver);
//根据url创建数据库连接对象Connection 
Connection con = DriverManage.getConnection(url,user,pwd);
//用数据库连接对象创建Statement对象(或PrepareStatement)
Statement s = con.createStatement();
或
PrepareStatement ps = con.PrepareStatement(sql);
//做数据库的增删改查工作
ResultSet rs = s.executeQuery();
//关闭结果集对象Resultset,statement对象,connection对象,
rs.close();
s.close();
con.close();
//各个步骤的异常处理

2.数据库连接使用的是桥接模式

桥接模式:

定义 :将抽象部分与它的实现部分分离,使它们都可以独立地变化。

意图 :将抽象与实现解耦。

桥接模式所涉及的角色

  1. Abstraction :定义抽象接口,拥有一个Implementor类型的对象引用
  2. RefinedAbstraction :扩展Abstraction中的接口定义
  3. Implementor :是具体实现的接口,Implementor和RefinedAbstraction接口并不一定完全一致,实际上这两个接口可以完全不一样Implementor提供具体操作方法,而Abstraction提供更高层次的调用
  4. ConcreteImplementor :实现Implementor接口,给出具体实现

Jdk中的桥接模式:JDBC

JDBC连接 数据库 的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不动,原因就是JDBC提供了统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了

3.对象的初始化方式

  1. new时初始化
  2. 静态工厂 newInstance;
  3. 反射Class.forName();
  4. clone方式;
  5. 反序列化;

4.Hibernate的POJO类对象

Hibernate Pojo的三态分别为transient(瞬时态),persistent(持久态),detached(游离态)

1、官方给出的三态与Session的关系如下:

transient: never persistent, not associated with any Session
persistent: associated with a unique Session
detached: previously persistent, not associated with any Session

2、三种状态间相互转换关系,及他们在数据库、session中的状态如下:

a.当我们new一个pojo时,它处于瞬时态,此时与session、数据库均无任何关联。

b.此后,我们获得session并开启hibernate事务,调用save(),persist(),saveOrUpdate()方法,将pojo转变为持久态,此时session中存有这个pojo,但直到transaction.commit()被调用时,sql语句才会执行,此后数据库中也才有此条数据。

c.但当commit()并且session.close()执行过后,pojo就变为了游离态,也就是说,数据库中有该记录,但session中不再有。

d.持久化状态的实例,也可以重新变成瞬时态,那就是调用delete()方法。

e.通过get()或load()方法得到的pojo是持久态的。

f.游离态的pojo可以通过update(),saveOrUpdate(),lock()和replicate()方法重新成为持久态。

g.调用merge()方法后,pojo维持原态,但内容会被更新到数据库

5.Java中类加载器

Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:

引导类加载器(bootstrap class loader)

它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。主要负责jdk_home/lib目录下的核心api 或 -Xbootclasspath 选项指定的jar包装入工作(其中的jdk_home是指配置jdk环境变量是java_home的配置路径,一般是jdk/jre所在目录)。

扩展类加载器(extensions class loader)

它用来加载 Java 的扩展库。Java虚拟机的实现会提供一个扩展库目录,扩展类加载器在此目录里面查找并加载 Java 类,主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。

系统类加载器(system class loader):

它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。主要负责CLASSPATH/-Djava.class.path所指的目录下的类与jar包装入工作.

除了系统提供的类加载器以外,开发人员可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器,从而进行动态加载class文件,以满足一些特殊的需求,这体现java动态实时类装入特性。

除了引导类加载器之外,所有的类加载器都有一个父类加载器,通过getParent()方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java 类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。下图中给出了一个典型的类加载器树状组织结构示意图,其中的箭头指向的是父类加载器。
在这里插入图片描述

6.Java中的关键字

在这里插入图片描述

7.多态的表现形式

定义:

多态是同一个行为具有多个不同表现形式或形态的能力。

存在的必要条件(表现形式):

  1. 继承
  2. 重写
  3. 父类引用指向子类对象:Parent p = new Child();

8.RMI

定义:

Java RMI,即 远程方法调用(Remote Method Invocation),一种用于实现远程过程调用(RPC)(Remote procedure call)的Java API, 能直接传输序列化后的Java对象和分布式垃圾收集。它的实现依赖于Java虚拟机(JVM),因此它仅支持从一个JVM到另一个JVM的调用。
在这里插入图片描述
                                              分布式架构基础:Java RMI详解

9.存根类

作用:

如果一个接口有很多方法,如果要实现这个接口,就要实现所有的方法。但是一个类从业务来说,可能只需要其中一两个方法。如果直接去实现这个接口,除了实现所需的方法,还要实现其他所有的无关方法。而如果通过继承存根类就实现接口,就免去了这种麻烦。

RMI 采用stubs 和 skeletons 来进行远程对象(remote object)的通讯。stub 充当远程对象的客户端,有着和远程对象相同的远程接口,远程对象的调用实际是通过调用该对象的客户端对象stub来完成的。

10.JSP中内置对象与获取方式

  1. out->response.getWriter
    out 对象用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区。在使用 out 对象输出数据时,可以对数据缓冲区进行操作,及时清除缓冲区中的残余数据,为其他的输出让出缓冲空间。待数据输出完毕后,要及时关闭输出流。
  2. request ->Service方法中的req参数
    request 对象是 javax.servlet.httpServletRequest类型的对象。 该对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。(包括头信息、系统信息、请求方式以及请求参数等)。request对象的作用域为一次请求。
  3. response ->Service方法中的resp参数
    response 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。response对象也具有作用域,它只在JSP页面内有效。
  4. session ->request.getSession
    1.什么是session:从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。当一个客户访问一个服务器时,可能会在这个服务器的几个页面之间反复连接,反复刷新一个页面,服务器应当通过某种办法知道这是同一个客户,这就需要session对象。
    2.session对象的ID:当一个客户首次访问服务器上的一个JSP页面时,JSP引擎产生一个session对象,同时分配一个String类型的ID号,JSP引擎同时将这个ID号发送到客户端,存放在Cookie中,这样session对象和客户之间就建立了一一对应的关系。当客户再访问连接该服务器的其他页面时,不再分配给客户新的session对象,直到客户关闭浏览器后,服务器端该客户的session对象才取消,并且和客户的会话对应关系消失。当客户重新打开浏览器再连接到该服务器时,服务器为该客户再创建一个新的session对象。
    3.session对象存在一定时间过期问题,所以存在session中的名值对会在一定时间后失去,可以通过更改session有效时间来避免这种情况。同时编程时尽量避免将大量有效信息存储在session中,request是一个不错的替代对象。
  5. application ->getServletContext
    1.什么是application:
    服务器启动后就产生了这个application对象,当客户在所访问的网站的各个页面之间浏览时,这个application对象都是同一个,直到服务器关闭。但是与session不同的是,所有客户的application对象都是同一个,即所有客户共享这个内置的application对象。
    2.application对象常用方法:
    (1)public void setAttribute(String key,Object obj): 将参数Object指定的对象obj添加到application对象中,并为添加的对象指定一个索引关键字。
    (2)public Object getAttribute(String key): 获取application对象中含有关键字的对象。
  6. exception ->Throwable
    java.lang.Throwable 的实例,该实例代表其他页面中的异常和错误。只有当页面是错误处理页面,即编译指令page 的isErrorPage 属性为true 时,该对象才可以使用。常用的方法有getMessage()和printStackTrace()等。
  7. page ->this
    page 对象代表JSP本身,只有在JSP页面内才是合法的。 page隐含对象本质上包含当前 Servlet接口引用的变量,类似于Java编程中的 this 指针。
  8. pageContext ->PageContext
    pageContext 对象的作用是取得任何范围的参数,通过它可以获取 JSP页面的out、request、reponse、session、application 等对象。pageContext对象的创建和初始化都是由容器来完成的,在JSP页面中可以直接使用 pageContext对象。
  9. Config ->getServletConfig
    config 对象的主要作用是取得服务器的配置信息。通过 pageContext对象的 getServletConfig() 方法可以获取一个config对象。当一个Servlet 初始化时,容器把某些信息通过 config对象传递给这个 Servlet。 开发者可以在web.xml 文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。

11.Servlet包中内容

javax.servlet 包中包含了 7 个接口 ,3 个类和 2 个异常类 , 它们分别是 :

接口 :RequestDispatcher,Servlet,ServletConfig,ServletContext,ServletRequest,ServletResponse 和 SingleThreadModel

类 :GenericServlet,ServletInputStream 和 ServletOutputStream

异常类 :ServletException 和 UnavailableException

12.静态域的初始化顺序

public class B
{
    
    
    public static B t1 = new B();
    public static B t2 = new B();
    {
    
    
        System.out.println("构造块");
    }
    static
    {
    
    
        System.out.println("静态块");
    }
    public static void main(String[] args)
    {
    
    
        B t = new B();
    }
}
//Output:构造块 构造块 静态块 构造块

正确的理解是这样的:

并不是静态块最先初始化,而是静态域.(BM:啊!多么痛的领悟!)

而静态域中包含静态变量、静态块和静态方法,其中需要初始化的是静态变量和静态块.而他们两个的初始化顺序是靠他们俩的位置决定的!

So!初始化顺序是 t1 t2 静态块

猜你喜欢

转载自blog.csdn.net/qq_52212721/article/details/112571563