汇总

###1.java基础

  1. JAVA 的基本数据类型有哪些 ? String 是不是基本数据类型 ?

    | 数据类型 | 关键字 | 内存占用 | 取值范围 |
    | :————–: | :—-: | :–: | :–: |
    | 字节型 | byte | 1 | -2的7次方~2的7-1(-128~127) |
    | 短整型 | short | 2 | -2的15次方~2的15-1(-32768~32767) |
    | 整型 | int | 4 | -231次方~2的31次方-1 |
    | 长整型 | long | 8 | -2的31次方~2的31次方-1 |
    | 单精度浮点数 | float | 4 | 1.4013E-45~3.4028E+38 |
    | 双精度浮点数 | double | 8 | 4.9E-324~1.7977E+308 |
    | 字符型 | char | 2 | 0-65535(0~2的16次方-1) |
    | 布尔类型 | boolean | 1 | true,false |

    String不是基本数据类型

    1个字节8个二进制位

  2. 说说& 和&& 的区别

    1.共同点

    &和&&都可以用作逻辑运算符,表示逻辑与(and),当运算符两边的表达式的结果都
    为 true 时,整个运算结果才为 true,否则,只要有一方为 false,则结果为 false。

    2.不同点

    &&还具有短路的功能,即如果第一个表达式为 false,则不再计算第二个表达式,例如,对
    于 if(str != null && !str.equals(“”))表达式,当 str 为 null 时,后面的表达式不会执行,所以不
    会出现 NullPointerException 如果将&&改为&,则会抛出 NullPointerException 异常。

    当然我们也应该用if(str != null && !“”.equals(str))

    &还可以用作位运算符,当&操作符两边的表达式不是 boolean 类型时,&表示按位与操作。

  3. short s1 = 1; s1 = s1 + 1; 有什么错? short s1 = 1; s1 += 1; 有什么错?

    对于 short s1 = 1; s1 = s1 + 1; 由于 s1+1 运算时会自动提升表达式的类型,所以结果是 int 型,
    再赋值给 short 类型 s1 时,编译器将报告需要强制转换类型的错误。
    对于 short s1 = 1; s1 += 1;由于 += 是 复合赋值操作符 ,java 编译器会自动地将所执行计算的结果转型为其左侧变量的类型 ,s1+=1等效于 s1=(short)(s1+1) ,因此可以正确编译

    但是请不要将复合赋值操作符作用于byte、short或char类型的变量 。

    因为S1是short型的,占2个字节,而100000是int型的,占4个字节。在两个类型的值相加的时候,会发生自动类型的提升,要不然数据也装不下呀。如果使用+=,会造成数值越界。

  4. char 型变量中能不能存贮一个中文汉字?

    char 型变量是用来存储 Unicode 编码的字符的,unicode 编码字符集中包含了汉字,所以,
    char 型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在 unicode 编码
    字符集中,那么,这个 char 型变量中就不能存储这个特殊汉字。补充说明:unicode 编码占
    用两个字节,所以,char 类型的变量也是占用两个字节。

  5. 使用 final 关键字修饰 一个变量时,是引用不能变,还是引用的对象不能变 ?

    使用 final 关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容

    还是可以改变的。

    例如,对于如下语句:
    final StringBuffer a=new StringBuffer(“immutable”);
    执行如下语句将报告编译期错误:
    a=new StringBuffer(“”);
    但是,执行如下语句则可以通过编译:
    a.append(“ broken!”);

  6. “==”和 和 equals 方法究竟有什么区别?

     1)对于==,比较的是值是否相等

                如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
    

         如果作用于引用类型的变量,则比较的是对象的地址是否相同

     2)equals方法,在Object类中,equals方法是用来比较两个对象的引用是否相等,即是否指向同一个对象 。

    public boolean equals(Object anObject) {//jdk1.8的equals部分源码
        if (this == anObject) {
            return true;
        }
        ...
    

    ​ 如String类当中重写了equals方法,比较的字符串的内容是否相同。

    注意:equals方法不能作用于基本数据类型的变量。

    ​ String类jdk1.9开始是private final byte value[];

  7. 静态变量和实例变量的区别?

  1. ###1. 0.面向对象

  2. 封装

  3. 继承

  4. 多态

  5. 抽象

####1.1.重用API

####1.2.框架

####1.3.多线程

synchronized锁静态方法相当于锁的是class文件(类)
锁普通方法锁的是堆内存的对象

####1.4.反射

#####1.4.1类加载的过程

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

加载

就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。

连接

验证 是否有正确的内部结构,并和其他类协调一致

准备 负责为类的静态成员分配内存,并设置默认初始化值

解析 将类的二进制数据中的符号引用替换为直接引用

初始化

就是给属性赋值

#####1.4..2类加载时机 -【面试题】

Ø 加载的原则-**用到的时候才加载字节码**

Ø 比如:

n 创建类的实例 new Student

n 访问类的静态变量,或者为静态变量赋值 Intergar.MAX_VALUE;

n 调用类的静态方法

n 初始化某个类的子类

n 直接使用java.exe命令来运行某个主类

n 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

#####1.4.3类加载器

类加载器的概述

负责将.class文件加载到内存中,并为之生成对应的Class对象。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。

1.4.4反射

https://blog.csdn.net/sinat_38259539/article/details/71799078

反射就是把java类中的各种成分映射成一个个的Java对象

反射是在java.lang.reflect这个包中

* 获取Class对象的方式:
    1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
        * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
    2. 类名.class:通过类名的属性class获取
        * 多用于参数的传递
    3. 对象.getClass():getClass()方法在Object类中定义着。
        * 多用于对象的获取字节码的方式

    * 结论:
        同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
public class Fanshe {
    public static void main(String[] args) {
        // 第一种方式获取Class对象
        Class stuClass1 = Student.class;

        //第二种方式获取Class对象
        try {
            Class stuClass2 = Class.forName("com.反射.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //第三种方式获取Class对象
        Student stu3 = new Student();//这一new 产生一个Student对象,一个Class对象。
        Class stuClass = stu1.getClass();//获取Class对象

    }
}
1.4.4.1获得构造方法

1.如果要使用反射,先要获取字节码对象

2.通过字节码对象的getConstructor()可以获取到构造方法对象

3.构造方法对象(Contructor),有个newInstance方法创建这个字节码对象

4.如果是私有的需要先调用setAccessible(true)设置访问权限,

5.反射的作用一般是用于写框架(ssh,ssm)

package com.反射;

/**
 * @author wangben
 * @Title: Student
 * @Package: com.反射
 * @ProjectName javase-code
 * @Description: TODO
 * @date 2019-01-27 13:25 星期日
 */
public class Student {

    private String name;
    private int age;

    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    private String getName() {return name;}

    private void setName(String name) {this.name = name;}

    private Student() {}

    private void add(int money){
        System.out.println("302加钱"+money);
    }

   @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

获得构造方法Constructor

批量的方法:
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有) 

获取单个的方法,并调用:
这里需要的是一个参数的类型,切记是类型。如果是无参的构造方法所以类型是一个null,也可以不写留空
public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

调用构造方法:
Constructor-->newInstance(Object... initargs)
* 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法(前提是构造器不能是私有的)
    Class clz = Class.forName("com.反射.Student");
    Student s =(Student)clz.newInstance();
//以私有的,参数为(String name)的构造器为例
  //1获取字节码class对象
 Class clz = Class.forName("com.反射.Student");
//获取私有的参数为(String name)构造方法
Constructor con = clz.getDeclaredConstructor(String.class,int.class);
System.out.println(con);
//调用构造方法
con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
Object obj = con.newInstance('栗子',25);
System.out.println(obj);
---------------------
private fanshe.Student(java.lang.String,int)
Student{name='栗子', age=25}

注意原始类型对应的虚拟机中的class实例和封装类对应的class实例是不相同的

如:

int 对应的class实例为 int.class 或者 Integer.TYPE,但是 Integer 对应的 class 实例为 Integer.class

######1.4.4.2获得属性

1.Class的getField(String)方法可以获取类中的指定字段(可见的),

2.如果是私有的,可以用getDeclaedField(“name”)方法获取

3.通过set(obj, “李四”)方法可以设置指定对象上该字段的值

4.如果是私有的需要先调用setAccessible(true)设置访问权限,

5.调用get(obj)可以获取指定对象中该字段的值

* Field[] getFields() :获取所有public修饰的成员变量
* Field getField(String name)   获取指定名称的 public修饰的成员变量

* Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
* Field getDeclaredField(String name)  获取指定名称的 不考虑修饰符

私有无参构造,私有name属性

package com.反射;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class Fanshe {
    public static void main(String[] args) {
        try {
            //1获取字节码class对象
            Class clz = Class.forName("com.反射.Student");
            //2.获得私有的无参构造
            Constructor con = clz.getDeclaredConstructor();
            con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
            //3 通过构造方法创建对象
            Object  o = con.newInstance();

            //4.获取私有name属性
            Field nameField = clz.getDeclaredField("name");
            System.out.println(nameField);

            //5.通过反射给私有属性赋值
            nameField.setAccessible(true);//设置私有属性可以访问
            nameField.set(o, "栗子");

            //6.通过反射获取私有属性name的值
            Object value = nameField.get(o);
            System.out.println(value);


        } catch (Exception e) {
            e.printStackTrace();
        }



    }
}
---------------------
private java.lang.String com.反射.Student.name
栗子

######1.4.4.3获得方法

1.反射中通过Method类描述方法【构造方法:Contructor,字段:Field】

2.通过Class的getMethod可以获取一个方法

3.通过getDeclaredMethod可以获取私有方法

4.如果要调用私有方法,设置访问权限setAccessible

5.method.invoke(list, “栗子”);

* Method[] getMethods()  获取所有"公有方法";(包含了父类的方法也包含Object类)
* Method[] getDeclaredMethods() 获取所有的成员方法,包括私有的(不包括继承的) 

    参数:
    name : 方法名;
    Class ... : 形参的Class类型对象
* Method getMethod(String name, 类<?>... parameterTypes)  
* Method getDeclaredMethod(String name, 类<?>... parameterTypes)  


package com.反射;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 获取Class对象的三种方式
 * 1 Object ——> getClass();
 * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
 * 3 通过Class类的静态方法:forName(String  className)(常用)
 *
 */
public class Fanshe {
    public static void main(String[] args) {
        try {
            //1获取字节码class对象
            Class clz = Class.forName("com.反射.Student");
            //2.获得私有的无参构造
            Constructor con = clz.getDeclaredConstructor();
            con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
            //3 通过构造方法创建对象
            Object  o = con.newInstance();

            //4.获取私有name属性
            Field nameField = clz.getDeclaredField("name");
            System.out.println(nameField);

            //5.通过反射给私有属性赋值
            nameField.setAccessible(true);//设置私有属性可以访问
            nameField.set(o, "栗子");

            //6.通过反射获取私有属性name的值
            Object value = nameField.get(o);
            System.out.println(value);

            //7.获得私有方法
            Method add = clz.getDeclaredMethod("add", int.class);
            add.setAccessible(true);//设置私有属性可以访问
            add.invoke(o,50);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
----------------------------
private java.lang.String com.反射.Student.name
栗子
302加钱50
1.4.4.4其他
File file = new File(Xml01.class.getClassLoader()
                .getResource("bean.xml").getPath());

E:\idea_project\javase-code\out\production\day01\bean.xml
E:\idea_project\javase-code\out\production\day01  //不带参数
---------------------------


File f = new File(Test.class.getResource("/").getPath());
E:\idea_project\javase-code\out\production\day01
E:\idea_project\javase-code\out\production\day01\com\wang //不带参数,反而带包

---------------------
String name = Test.class.getName();
com.wang.Test

------------------
String name = Test.class.getSimpleName();
Test
----------------

反射越过泛型
//1.声明泛型集合
        List<Integer> list = new ArrayList<Integer>();

        list.add(110);
        list.add(120);
        list.add(130);
        //list.add("lizi");

        //2.通过反射往集合添加字符串
        //2.1 获取字节码对象(Class)
        Class clz = list.getClass();

        //2.2 通过反射获取方法
        Method method = clz.getMethod("add", Object.class);

        //2.3 调用方法
        method.invoke(list, "lizi");

        System.out.println(list);

###2.javaweb

###3.框架

3.1.spring

  1. 介绍一下你对spring框架的理解

  2. 说一下spring的加载过程

  1. ioc与di的区别

    ####3.2.mybatis

    ####3.3.springmvc

    ####3.4.springboot

4.编程

####4.1 单例模式

https://blog.csdn.net/mnb65482/article/details/80458571

  1. 定义:保证一个类仅有一个实例,并提供一个全局的访问点。

  2. 应用场景:想确保任何情况下都绝对只有一个实例
    需要频繁实例化然后销毁的对象(数据连接池,多线程线程池)

    1. 网站的计数器,一般也是采用单例模式实现,否则难以同步

    2. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

    3. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。

  3. 优点
    1.对于一些需要频繁创建和销毁的对象来说可以提高系统的性能。
    2.实现了对唯一实例访问的可控

  4. 缺点
    1.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
    2.如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失。
    3..滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出。

  5. 单例代码

    1. 单例模式分类

      1. 懒汉式

        2. 饿汉式
        
    2. 单例模式要素:

      a. 私有构造方法

      b. 私有静态引用指向自己实例

      c. 以自己实例为返回值的公有静态方法

      ​ 为什么是静态变量和静态方法?

      单例就是说一个类仅有一个实例。

      首先构造器是私有的。私有的构造器防止其他程序创建该类的对象,

      我们就需要创建一个私有的引用指向自己的实例,提供一个公共的获取单例的方法

      调用类中方法有两种方式

      ①创建类的一个对象,用对象去调用方法;②使用类名直接调用类中方法。

      显然第一种情况不能用,只能使用第二种方法。而想要使用类名直接调用类中方法,类中方法必须是静态的,而静态方法不能访问非静态成员变量,因此私有引用也必须是静态的。

4.1.1饿汉式与懒汉式

1、饿汉式:(比较饿)在单件模式类被加载的时候,单件模式实例就已经被创建。

2、懒汉式:(比较懒)当程序第一次访问单件模式实例时才进行创建。

如何选择:如果单件模式实例在系统中经常会被用到,饿汉式是一个不错的选择。

反之如果单件模式在系统中会很少用到或者几乎不会用到,那么懒汉式是一个不错的选择。

懒汉式

懒汉模式在方法被调用后才创建对象,以时间换空间,在多线程环境下存在风险。

多线程时不安全

  public class SingleTon{
   private static SingleTon  INSTANCE = null;
   private SingleTon(){}
   public static SingleTon getInstance() {  
   if(INSTANCE == null){
         //多线程时,假如多个线程进入if里会创建多个对象
      INSTANCE = new SingleTon(); 
    } 
    return INSTANCE;
  }
  }

改进加锁

  public class SingleTon{
   private static SingleTon  INSTANCE = null;
   private SingleTon(){}
   //synchronized加锁解锁消耗资源,而且加在静态方法上相当于锁类,范围大
   public synchronized static SingleTon getInstance() {  
   if(INSTANCE == null){
      INSTANCE = new SingleTon(); 
    } 
    return INSTANCE;
  }
  }

再改进双重检查锁(DCL模式)

只有在对象需要被使用时才创建,第一次判断 Bean== null为了避免非必要的加锁,当第一次加载时才对实例进行加锁再实例化。这样既可以节约内存空间,又可以保证线程安全。但是,由于jvm存在乱序执行功能,DCL也会出现线程不安全的情况。具体分析如下:

1.在堆内存开辟内存空间。
2.在堆内存中实例化SingleTon里面的各个参数(初始化对象)。
3.把对象指向堆内存空间。

由于jvm存在乱序执行功能,所以可能在2还没执行时就先执行了3,如果此时再被切换到线程B上,由于执行了3,INSTANCE 已经非空了,会被直接拿出来用,这样的话,就会出现异常。这个就是著名的DCL失效问题。
volatile确保INSTANCE每次均在主内存中读取。

  public class Bean {
      //volatile保证线程对其他线程的可见性
      //为了防止多线程指令重排序的问题
      private volatile static Bean bean = null;
      private Bean(){ }
      public  static Bean getBean(){
          if (bean == null){
              synchronized(Bean.class) {
                  if (bean == null) {
                      bean = new Bean();
                  }
              }
          }
          return bean;
      }
  }
饿汉式

饿汉模式在类被初始化时就已经在内存中创建了对象,以空间换时间,故不存在线程安全问题 。

  public class SingleTon{
         private static SingleTon INSTANCE = new SingleTon();
       private SingleTon(){}
      public static SingleTon getInstance(){ return INSTANCE; }}

静态内部类

外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。即当SingleTon第一次被加载时,并不需要去加载SingleTonHoler,只有当getInstance()方法第一次被调用时,才会去初始化INSTANCE,第一次调用getInstance()方法会导致虚拟机加载SingleTonHoler类,这种方法不仅能确保线程安全,也能保证单例的唯一性,同时也延迟了单例的实例化。

  //基于类的初始化延时加载实现
  public class SingleTon{
  private SingleTon(){}
  private static class SingleTonHoler{
     private static SingleTon INSTANCE = new SingleTon();
   }
  public static SingleTon getInstance(){
    return SingleTonHoler.INSTANCE;
  }
  }

  //由于是静态内部类的形式去创建单例的,故外部无法传递参数进去,例如Context这种参数,
  所以,我们创建单例时,可以在静态内部类与DCL模式里自己斟酌

暴力反射
类加载时就创造对象的饿汉式,静态内部类(加载内部类时创建对象),

暴力反射饿汉式代码,静态内部类方式同理,不做重复。

 public static void main(String[] args) throws Exception {

        //反射获得
        Class<?> c1 = Class.forName("com.反射.SingleTon");
        Constructor declaredConstructor = c1.getDeclaredConstructor();
        //setAccessible值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
        declaredConstructor.setAccessible(true);
        SingleTon singleTon = (SingleTon)declaredConstructor.newInstance();

        //通过面向外部公共访问方法获得
        SingleTon instance = SingleTon.getInstance();

        System.out.println(instance);
        System.out.println(singleTon);
        System.out.println(instance== singleTon);
    }

   ----------------------------
       com.反射.SingleTon@677327b6
    com.反射.SingleTon@14ae5a5
      false

防止代码

饿汉式


public class SingleTon{
    private static SingleTon INSTANCE = new SingleTon();
    private SingleTon(){
        if(INSTANCE!=null){
            throw new RuntimeException("单例模式禁止反射");
        }
    }
    public static SingleTon getInstance(){ return INSTANCE; }}
--------------------
Exception in thread "main" java.lang.reflect.InvocationTargetException
 ...
Caused by: java.lang.RuntimeException: 单例模式禁止反射
    at com.反射.SingleTon.<init>(SingleTon.java:15)
    ... 5 more

懒汉时好像不能防止,有时间再看

即使加了判断,如果反射线程先进入 private SingleTon()里,还没创建对象,就不会RuntimeException

public class SingleTon{
    private SingleTon(){
        //如果反射线程先进入,还没创建对象,就不会RuntimeException
        if(INSTANCE!=null){
            throw new RuntimeException("单例模式禁止反射");
        }
    }
    private static SingleTon  INSTANCE = null;
    public static SingleTon getInstance() {
        if(INSTANCE == null){

            INSTANCE = new SingleTon();
        }
        return INSTANCE;
    }
}
枚举实现单例

即可防止暴力反射,序列化也咩问题,多线程可可以

package com.设计模式.单例模式;

public enum EnumSingleton {
    INSTANCE;
    private Object date;

    public Object getDate() {
        return date;
    }

    public void setDate(Object date) {
        this.date = date;
    }

    public static EnumSingleton getEnumSingleton() {
        return INSTANCE;
    }
}

4.2代理模式

4.2.1 静态代理

静态代理的实现比较简单,代理类通过实现与目标对象相同的接口,并在类中维护一个代理对象。通过构造器塞入目标对象,赋值给代理对象,进而执行代理对象实现的接口方法,并实现前拦截,后拦截等所需的业务功能。

https://www.jb51.net/article/124323.htm


4.2.2动态代理


转载请注明: Hexo 汇总

上一篇
网络编程 网络编程
【网络编程】主要内容 软件架构CS/BS 网络通信三要素 TCP通信 Socket套接字 ServerSocket 教学目标 能够辨别UDP和TCP协议特点 能够说出TCP协议下两个常用类名称 能够编写TCP协议下字符串数据传输程序
2019-01-26
下一篇
dom4j解析xml(demo) dom4j解析xml(demo)
转载自: ​ https://www.cnblogs.com/sharpest/p/7877501.html ​ https://www.cnblogs.com/hongwz/p/5514786.html 感谢
2019-01-25