Java复习-散乱知识点1

1、同步与异步 阻塞和非阻塞

1.1.同步与异步
同步与异步其实是指对CPU时间片的利用,主要是看请求发起方,对消息的获取是主动发起的还是被动通知的.

  • 如果是主动发起的,一直在等待应答结果(同步阻塞),或者可以处理其他事情,但要不断轮询查看发起的请求是否有应答结果(同步非阻塞)
  • 如果是由服务方通知的也就是请求方发出请求后,要么一直等待通知(异步阻塞),要么先去干自己的事情(异步非阻塞),当事情处理完成后,服务方会主动通知请求方,它的请求已经完成,这就是异步,异步通知的方式有状态改变,消息通知,或者回调函数来完成,大多数时候采用的都是回调函数

1.2阻塞与非阻塞

阻塞与非阻塞通常是指的针对IO的操作,简单的说,就是我们调用了一个函数后,再等待这个函数返回结果之前,当前的线程是处于挂起状态,还是运行状态,如果是挂起状态,就意味着当前线程什么都不能干,就等着获取结果,这就是同步阻塞,如果仍然是运行状态,就意味着当前线程是可以继续处理其他任务的,就是非阻塞状态

2、进程和线程的区别

  • 进程是系统进行资源分配和调度的一个独立单位,进程有独立的地址空间 线程
  • 是进程的一个实体,是CPU调度和分配的基本单位,它是比进程更小的能独立运行的基本单位, 一个程序至少有一个进程,一个进程至少有一个线程
  • 线程执行开销小,但不利于资源的管理和保护,而进程正相反

3、内部类

3.1、为什么使用内部类?

  • 使用内部类最大的优点就在于它能够非常好的解决多重继承的问题,使用内部类还能够为我们带来如下特性:
    1).内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独。
    2).在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
    3).创建内部类对象的时刻并不依赖于外围类对象的创建。
    4).内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。

3.2、内部类分类

3.2.1成员内部类

public class Outer{
    
    
      private int age = 99;
      String name = "Coco";
      public class Inner{
    
    
          String name = "Jayden";
          public void show(){
    
    
              System.out.println(Outer.this.name);
              System.out.println(name);
              System.out.println(age);
          }
      }
      public Inner getInnerClass(){
    
    
          return new Inner();
      }
      public static void main(String[] args){
    
    
          Outer o = new Outer();
          Inner in = o.new Inner();
          in.show();
      }
  }

注意:
	01、Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,如 publicprotectedprivate02、Inner 类中定义的 show() 方法可以直接访问 Outer 类中的数据,而不受访问控制符的影响,如直接访问 Outer 类中的私有属性age
	03、外部类是不能直接使用内部类的成员和方法的,可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法;
	04、如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,可以使用 this 关键字,:Outer.this.name

3.2.2成员内部类

/*
1.静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问,比如我们访问age,可以使用 new Outer1().age直接访问。
2.如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员
3.创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名 = new 内部类();
*/
public class Outer1 {
    
    
    private int age = 99;
    static String name = "Coco";
    public static class Inner{
    
    
        String name = "Jayden";
        public void show(){
    
    
            System.out.println(Outer1.name);
            System.out.println(name);
            System.out.println(new Outer1().age);
        }
    }
    public static void main(String[] args){
    
    
        Inner i = new Inner();
        i.show();
    }
}

3.2.3方法内部类:其作用域仅限于方法内,方法外部无法访问该内部类
3.2.4匿名内部类

/*
1、匿名内部类是直接使用 new 来生成一个对象的引用;
*/
public class OuterClass {
    
    
          public InnerClass getInnerClass(final int   num,String str2){
    
    
              return new InnerClass(){
    
    
                  int number = num + 3;
                  public int getNumber(){
    
    
                      return number;
                  }
              };        /* 注意:分号不能省 */
          }
          public static void main(String[] args) {
    
    
              OuterClass out = new OuterClass();
              InnerClass inner = out.getInnerClass(2, "chenssy");
              System.out.println(inner.getNumber());
          }
      }
      interface InnerClass {
    
    
          int getNumber();
      }

4、Spring Bean生命周期

生命周期的三个阶段

4.1创建阶段
scope = “singleton”(默认)

Spring工厂创建的同时,对象创建
ClassPathXmlApplicationContext s1 = new ClassPathXmlApplicationContext("application.xml");

注意:lazy-init="true" 这种情况下是在获取对象的时候才创建
<bean name="student" class="com.zq.student" scope="singleton" lazy-init="true"/>

scope = “prototype”

Spring工厂在获取对象的时候创建对象.

ClassPathXmlApplicationContext s1 = new ClassPathXmlApplicationContext("application.xml");
Object student = s1.getBean("student");

4.2初始化阶段

4.3销毁阶段

5、数组学习

1、可用于存储多个数据,每个数组元素存储一个数据,通常可
通过数组元素的索引来访问数组元素,包括为数组元素赋值和取出数组元素的值。

5.1、Java的数组要求所有的数组元素具有相同的数据类型。

5.2数组的特点:

  • 数组初始化完成后,数组在内存中所占的空间将被固定下来,数组元素发生任何变化(包括清空), 数组的长度将不可改变。
  • 数组即可以存储基本数据类型,也可存储引用类型。只要所有的数组元素具有相同的类型即可。
  • 数组是引用类型,即可以被另一个数组所存储。

5.3.数组的初始化有如下两种方式:

  • 静态初始化:初始化时由程序员显式的指定每个数组元素的初始值,由系统决定数组的长度。
  • 动态初始化:初始化时数组长度由程序员指定或程序指定,由系统为元素分配初始值。

静态初始化

//定义一个int[]类型的数组,并静态初始化。
int[] arrayInt = new int[]{
    
    1,2,3,4,5};

//上面的代码等价于下面的代码
int[] arrayInt1;
arrayInt1 = new int[]{
    
    1,2,3,4,5};

//上面的代码等价于下面的代码
int[] arrayInt2 = {
    
    1,2,3,4,5};

动态初始化

声明数组类型与静态初始化指定的数组元素相同
int[] arrayInt = new int[5];

5.4、访问数组元素和数组的遍历

数组长度属性 length
length是数组的长度属性,通过此属性可以获取数组的长度,然后依靠此属性可以查询(打印)数组的值以及动态的为数组赋值。

数组长度属性例子
//1.查询(打印)数组的值
public class J_ArrayDemo3 {
    
    
    public static void main(String[] args) {
    
    
        int[] arrayInt = new int[8];
        for (int i = 0; i < arrayInt.length; i++) {
    
    
            System.out.println(arrayInt[i]);
        }
    }
}

遍历数组——数组和集合的专属循环foreach
foreach循环语法
for(数组类型 变量:数组变量(集合变量)){
//自动访问(迭代)每个元素
}

public class J_ArrayDemo5 {
    
    
	public static void main(String[] args) {
    
    
	    String[] books = {
    
    "疯狂Java","狂神说","小滴课堂","黑马","尚学堂"};
	    for (String a : books) {
    
    
	        System.out.println(a);
	    }
	}
}

5.4.1、数组中常用的方法

sort

/*
数组的工具类java.util.Arrays
数组对象本身没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些计本的操作
常用功能:
给数组赋值,通过fill方法
对数组排序,通过sort方法
比较数组,通过equal方法比较数组中元素的值是否相等
查找数组元素,通过binary Search方法能对排序好的数组进行二分查找法操作
*/
public class J_ArrayDemo22 {
    
    
    public static void main(String[] args) {
    
    
        /*
         * 对数组arrayType的元素进行排序
         * void sort(type[] arrayType);
         * 对数组arrayType所在范围内的元素进行排序
         * void sort(type[] arrayType,int fromIndex,int toIndex)
         */
        int[] arrayInt = {
    
    22,34,11,25,28,12};
        int[] arrayInt1 = {
    
    22,34,11,25,28,12};
        Arrays.sort(arrayInt);
        for (int a : arrayInt){
    
    
            System.out.print(a + ",");
        }
        System.out.println();
        Arrays.sort(arrayInt1,2,4);
        for (int a : arrayInt1){
    
    
            System.out.print(a + ",");
        }
    }
}

toString

public class J_ArrayDemo23 {
    
    
    public static void main(String[] args) {
    
    
    /*
     * String toString(type[] arrayType)
     * 将数组转化为字符串。
     */
        int[] arrayInt1 = null;
        int[] arrayInt2 = new int[0];
        int[] arrayInt3 = {
    
    1};
        int[] arrayInt4 = {
    
    1,12,23,4,1,2,3,1};
        System.out.println(Arrays.toString(arrayInt1));
        System.out.println(Arrays.toString(arrayInt2));
        System.out.println(Arrays.toString(arrayInt3));
        System.out.println(Arrays.toString(arrayInt4));
    }
}

6、栈与堆

  • 栈:当一个方法执行时,会在内存栈中开辟一块属于自己的空间,此方法中的变量会放在此空间中,随着方法的结束变量和方法中的变量被销毁。
  • 堆:在程序中创建一个对象时,这个对象将被保存到堆中,对象不会随着方法的结束而销毁,即使方法结束后,这个对象还可以被其他引用变量所引用,只有当没有被任何引用变量所引用时,才会在系统空闲时,被系统垃圾回收机制回收。

7、过滤器和拦截器的区别:

①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

8、jsp和servlet有哪些异同,之间联系是什么?

1.jsp经编译后就变成了servlet(jsp本质就是servlet,jvm只能识别java的类,不能识别jsp代码,web容器将jsp的代码编译成jvm能够识别的java类)

2.jsp更擅长表现于页面显示,servlet更擅长于逻辑控制

3.setvlet中没有内置对象,jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象及HttpServlet对象得到

4.jsp是servlet的一种简化,使用jsp只需要完成程序员需用输出到客户端的内容,jsp中的java脚本如何镶嵌到一个类中,由jsp容器完成,而servlet则是个完整的java类,这个类的service方法用于生成对客户端的响应

9、一次完整的http请求是什么样的?

1.解析URL

首先浏览器会检测这个url是否正确存在,如果不合法,将会返回一个默认的搜索引擎。
如果存在并合法,那么可以解析得到协议(http或者https)、域名(baidu)、资源(首页)等信息。

2.DNS查询
浏览器会先检查域名信息是否在缓存中。
再检查域名是否在本地的Hosts文件中。
如果还不在,那么浏览器会向DNS服务器发送一个查询请求,获得目标服务器的IP地址

3.TCP传输及运输
这时候浏览器获得了目标服务器的IP(DNS返回)、端口(URL中包含,没有就使用默认(HTTP默认80端口)),浏览器会调用库函数socket,生成一个TCP流套接字,也就是完成了TCP的封包。
TCP封包完成之后,就可以传输了,浏览器和服务器就完成了TCP的三次握手,建立了连接,后面就可以请求服务器资源了。

4.服务器接收请求并响应
HTTP有很多请求方法,比如:GET/POST/PUT/DELETE等等,我们浏览器输入URL这种,是GET方法。
服务器接收到GET请求,服务器根据请求信息,获得相应的相应内容。例如我们输入的是:\百度一下,你就知道\,那么意味着访问百度的首页文件

5.浏览器解析并渲染
浏览器从服务器拿到了想要访问的资源,大多数时候,这个资源就是HTML页面,当然也可能是一个其他类型的文件。
浏览器先对HTML文档进行解析,生成解析树(以DOM元素为节点的树)。
加载页面的外部资源,比如JS、CSS、图片。
遍历DOM树,并计算每个节点的样式,最终完成渲染,变成我们看到的页面。

10、页面跳转的两种实现方式:请求转发和重定向

请求转发:
客户首先发送一个请求到服务器端,服务器端发现匹配的servlet,并指定它去执行,当这个servlet执行完之后,它要调用getRequestDispacther()方法,把请求转发给指定的student_list.jsp,整个流程都是在服务器端完成的,而且是在同一个请求里面完成的,因此servlet和jsp共享的是同一个request,在servlet里面放的所有东西,在student_list中都能取出来,因此,student_list能把结果getAttribute()出来,getAttribute()出来后执行完把结果返回给客户端。整个过程是一个请求,一个响应。

重定向:
客户发送一个请求到服务器,服务器匹配servlet,servlet处理完之后调用了sendRedirect()方法,立即向客户端返回这个响应,响应行告诉客户端你必须要再发送一个请求,去访问student_list.jsp,紧接着客户端收到这个请求后,立刻发出一个新的请求,去请求student_list.jsp,这里两个请求互不干扰,相互独立,在前面request里面setAttribute()的任何东西,在后面的request里面都获得不了。可见,在sendRedirect()里面是两个请求,两个响应。(服务器向浏览器发送一个302状态码以及一个location消息头,浏览器收到请求后会向再次根据重定向地址发出请求)

请求转发:request.getRequestDispatcher(“/test.jsp”).forword(request,response);
重定向:response.sendRedirect(“/test.jsp”);

区别:

1、请求次数:重定向是浏览器向服务器发送一个请求并收到响应后再次向一个新地址发出请求,转发是服务器收到请求后为了完成响应跳转到一个新的地址;重定向至少请求两次,转发请求一次;

2、地址栏不同:重定向地址栏会发生变化,转发地址栏不会发生变化;

3、是否共享数据:重定向两次请求不共享数据,转发一次请求共享数据(在request级别使用信息共享,使用重定向必然出错);

4、跳转限制:重定向可以跳转到任意URL,转发只能跳转本站点资源;

5、发生行为不同:重定向是客户端行为,转发是服务器端行为;

11、常见的http返回状态码(200,301,302,400)

200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误

猜你喜欢

转载自blog.csdn.net/Anna_Liqi/article/details/114433653