# 技术栈知识点巩固——Java

Hellow World

  • 输入参数,在控制条打印出参数
package java.lang;

public final class System {

     public final static PrintStream out = null;
    
}

package java.io;
public class PrintStream extends FilterOutputStream
    implements Appendable, Closeable
{
    // ...
	 public void println() {
        newLine();
    }
}

对象和类

  • 对象:对象是类的一个实例,有状态、属性、行为。

  • 类:类是一个模板,它描述一类对象的行为和状态。

public class ClassTest1 {
    //类变量
    private static String name;
    //成员变量
    int age;
    public static void main(String[] args) {
        //局部变量
        int i=0;
    }
}

java基本数据类型

类型长度(字节)包装类
long8java.lang.Lang
float4java.lang.Float
double8java.lang.Double
bollean默认值false
char2java.lang.Character
byte1java.lang.Byte
short2java.lang.short
int4java.lang.Integer
  • 引用类型:Test test=new Test();对象数组都是引用数据类型,所有应用类型的默认值都是nill。

  • java常量:使用final修饰常量


java访问控制修饰符

  • default 默认:在同一个包内可见,不用任何修饰符。
  • private:同一类可见。
  • public:对所有类可见。
  • protected:对同一包内的类和所有子类可见。

equals与==的区别

  • 基本数据类型:equals不能比较基本数据类型的变量,==比较的是对象的内容是否相等。
  • 引用数据类型:equals默认比较的是地址是否相等,当重写了equals方法后比较的是对象的内容是否相同,==比较的是所指向的对象的地址。
// Object 中的默认equals()
public boolean equalsequals(Object obj) {
    return (this == obj);
}
  • Objectequals比较的是对象的地址是否相同,String重写 equals比较的是对象的地址上的值是否相等。
// String 重写equals()
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

final, finally, finalize 的区别

final

  • final修饰的类不能被继承(String类)修饰的类中的方法不能被重写。
  • final修饰的变量为常量只能赋值一次

finally

  • 除非上面的代码抛出异常,finally中的代码一定会执行,即使上面有return语句
try{
    
}catch(Exception e){
    
}finally{
    // 代码一定会执行
}

finalize

  • Objectprotected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。

泛型

  • 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
// 泛型方法
private <T> T dealObject(T t) {
    return t;
}
// 类型通配符
private void addArray(List<?> list) {
    logger.info(String.valueOf(list.get(0)));
}
// 泛型类
public class ResultInfo<T> {

    private T data;
    private String code;
    private boolean success;
	
    // ..get、set()
}

抽象类和接口有什么区别

  • 接口中没有构造方式。接口中的方法必须是抽象的,接口中除了static、final变量,不能有其他变量。接口支持多继承(一个类可以实现多个接口)。
  • 抽象类可以有构造方法,接口中不能有构造方法。抽象类中可以有普通成员变量,接口中没有普通成员变量。抽象类中可以包含静态方法,接口中不能包含静态方法。一个类可以实现多个接口,但只能继承一个抽象类。接口可以被多重实现,抽象类只能被单一继承。如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法。

BIO、NIO、AIO 有什么区别


String,Stringbuffer,StringBuilder的区别

  • String:字符串常量,把数据存放在了常量池中。
  • StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况。
  • StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况。

JAVA中的几种基本数据类型是什么,各自占用多少字节呢


Comparator与Comparable

  • Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
@FunctionalInterface
public interface Comparator<T> {}

public interface Comparable<T> {}

String类能被继承吗

  • 直接上源码
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {}
  • final关键字修饰的类。

说说Java中多态的实现原理

  • 多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定。
  • 举个例子:工厂模式一个工厂可以拿到具体的不同的工厂对象。

Java泛型和类型擦除

  • 泛型类
public class Test<T> {
    T t;
}
  • 泛型方法
public <T> T getObject(T t) {
    return t;
}
  • 泛型接口
public interface List<E> extends Collection<E> {}
  • 泛型存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。

说说反射的用途及实现原理,Java获取反射的三种方法

  • 动态地发现和绑定类、方法、字段,以及所有其他的由于有所产生的的元素。通过反射,能够在需要时完成创建实例、调用方法和访问字段的工作。
  • 反射的实现
@Test
public void t1() {
    try {
        // 使用Class类的fornName静态方法获得类的对象
        Class clazz = Class.forName("clazz.reflection.ReflectionClass");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method x : declaredMethods) {
            System.out.println(x);
        }
        // newInstance()和 new 有相同的功能,但是newInstance实现动态加载类,newInstance通过调用无参的构造方法
        // newInstance()分解为两个步骤,先加载某个类,然后进行实例化。
        ReflectionClass reflectionClass = (ReflectionClass) clazz.newInstance();
        reflectionClass.show();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    }
}

@Test
public void t2() {
    ReflectionClass reflectionClass = new ReflectionClass();
    // getClass方法获得这个类的对象
    Class<? extends ReflectionClass> aClass = reflectionClass.getClass();
    Method[] declaredMethods = aClass.getDeclaredMethods();
    Stream.of(declaredMethods).forEach(System.out::println);
}


@Test
public void t3() {
    // 直接使用.class方法,他会自动去匹配
    Class clazz = ReflectionClass.class;
    Method[] declaredMethods = clazz.getDeclaredMethods();
    Stream.of(declaredMethods).forEach(System.out::println);
}

Java中IO流


类的实例化顺序

  • 父类静态代码块
  • 子类静态代码块
  • 父初始化块
  • 父构造方法
  • 子初始化块
  • 子构造方法

Java创建对象有几种方式

@Test
public void createObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    User user = new User();
    Object user1 = Class.forName("entity.User").newInstance();
    User user2 = User.class.newInstance();
    logger.info("{} {} {}", user, user1, user2);
}
  • 反序列化
  • 调用clone方法

notify()和 notifyAll()有什么区别?

  • notify()方法(只随机唤醒一个 wait 线程),notifyAll()方法(唤醒所有 wait 线程)

Java的异常

  • 图片来自:http://c.biancheng.net/view/6635.html

img


String s = "test"的创建过程

  • 先在字符串常量池中寻找是否存在test的常量,如果存在则直接将常量池中的地址指向s
  • 如果不存在,则在常量池中新建一个test并放入常量池里面,然后再返回该地址。

String s = new String(“test”)

  • 先在字符串常量池中寻找是否存在test的常量
  • 有的话在堆中复制一个该字符串,并且将堆中的引用指向s。创建一个对象。
  • 没有的话,先在字符串常量池中先创建一个字符串为test的常量,然后再复制到堆里面,最后将堆所在的地址指向s。总共创建两个对象。

Class.forName和ClassLoader的区别

  • Class.forName加载并初始化了一个类。

  • ClassLoader仅加载了类。

  • Class.forName:中调用ClassLoader的方法。

@CallerSensitive
public static Class<?> forName(String className)
    throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass();
    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

JDK动态代理与cglib实现的区别

  • JDK 动态代理是面向接口的;
  • CGLib 动态代理是通过字节码底层继承代理类来实现,如果被代理类被 final 关键字所修饰,则无法被代理。

jdk动态代理

  • 定义一个接口
  • 编写接口实现类
  • 编写实现 InvocationHandler接口的类,代理类的方法调用会被转发到该类的invoke()

cglib

  • 实现一个MethodInterceptor,方法调用被转发到该类的 intercept()
  • 使用 Enhancer 获取代理对象,并调用对应的方法

自定义注解的场景及实现


说说你熟悉的设计模式

  • 详细内容见博客:https://blog.csdn.net/qq_37248504/article/details/117753021

  • 工厂模式:实现解耦,将对象的创建和使用分开,多态的充分体现。

  • 单例模式:需要频繁实例化然后销毁的对象,创建对象时耗时过多或者耗资源过多,但又经常用到的对象。

  • 策略模式:形成多种决策,优化代码。

  • 代理模式:找到中介租房子。

  • 适配器模式:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。


抽象工厂和工厂方法模式的区别

  • 工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的。

什么是值传递和引用传递

  • 值传递:形参是实参的拷贝,改变形参的值并不会影响外部实参的值。
  • 引用传递:传递的是对象的引用,改变引用的对象,之前的对象也会改变。

可以在static环境中访问非static变量吗?

  • 不可以,因为static变量是属于类的,在类加载的时候就被初始化了,这时候非静态变量并没有加载,故非静态变量不能访问。

Java支持多继承么,为什么

  • 类只支持单继承,而接口可以实现多继承。

用最有效率的方法计算2乘以8?

int a = 2<<3;

构造器是否可被重写?

  • Constructor 不能被继承, 所以不能被 override. 每一个类必须有自己的构造函数, 负责构造自己这部分的构造。子类不会覆盖父类的构造函数, 相反必须负责在一开始调用父类的构造函数。

char型变量中能不能存贮一个中文汉字,为什么?

  • 一个char类型占2个字节(16比特),所以放一个中文是没问题的。
  • char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode

实现对象克隆

  • 实现Cloneable接口,将clone()方法重写为public
  • 浅克隆:克隆对象自身引用的地址
  • 深克隆:克隆对象自身以及对象所包含的引用类型对象的引用地址
public class Student implements Cloneable {

    private String name;
    private String sno;

    // set、get...
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

hashCode的作用是什么?

public native int hashCode();
  • hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。

写出几种单例模式实现,懒汉模式和饿汉模式区别


泛型的存在是用来解决什么问题

  • 在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率,避免在运行时出现 ClassCastException

什么是序列化,怎么序列化,反序列

  • Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程。
  • 通过序列化永久性保存对象,保存对象的字节序列到本地文件或者数据库中;
  • 通过序列化以字节流的形式使对象在网络中进行传递和接收;
  • 通过序列化在进程间传递对象;
@Test
public void testTwo() throws IOException, ClassNotFoundException {
    //序列化
    FileOutputStream fileOutputStream = new FileOutputStream("object.txt");
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
    User user1 = new User(1, "123456", "male");
    objectOutputStream.writeObject(user1);
    objectOutputStream.flush();
    objectOutputStream.close();
    //反序列化
    FileInputStream fileInputStream = new FileInputStream("object.txt");
    ObjectInputStream ois = new ObjectInputStream(fileInputStream);
    User user2 = (User) ois.readObject();
    logger.info(user2.getId() + " " + user2.getName() + " " + user2.getAddress());
}

java8的新特性。


简述一下面向对象的”六原则一法则”

  • 单一职责原则:一个类只做一件事情
  • 开闭原则:对修改关闭,对扩展开放。
  • 依赖倒转:参数、方法返回类型等尽可能使用抽象类,抽象类型可以被它的任何一个子类型所替代。
  • 里氏替换:任何时候都可以用子类型替换掉父类型,子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多。
  • 接口隔离:接口要小而专,绝不能大而全。
  • 合成聚合复用:优先使用聚合或合成关系复用代码。
  • 迪米特法则:最少知识原则,一个对象应当对其他对象有尽可能少的了解。

switch作用类型

  • char, byte, short, int, Character, Byte, Short, Integer, String, or an enum

同步和异步有什么区别?

  • 同步:同步是指一个进程在执行某个请求的时候,如果该请求需要一段时间才能返回信息,那么这个进程会一直等待下去,直到收到返回信息才继续执行下去。

  • 异步:异步是指进程不需要一直等待下去,而是继续执行下面的操作,不管其他进程的状态,当有信息返回的时候会通知进程进行处理,这样就可以提高执行的效率了


什么是serialVersionUID

  • serialVersionUID适用于java序列化机制。简单来说,JAVA序列化的机制是通过 判断类的serialVersionUID来验证的版本一致的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID于本地相应实体类的serialVersionUID进行比较。如果相同说明是一致的,可以进行反序列化,否则会出现反序列化版本一致的异常,即是InvalidCastException

Java 中,DOM 和SAX 解析器有什么不同?


Java四大引用

作用

  • 灵活的控制对象的生命周期

  • 提高对象的回收机率

类型

  • 强引用:gc永不回收强引用的对象, 即使jvm出现内存溢出错误,使程序停止,也不会回收对象来提高内存。
  • 软引用:当内存不足,gc对软引用对象进行回收。
  • 弱引用:只要被gc发现弱引用,不管内存够不够,直接回收。
  • 虚引用:虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。
@Test
public void test3() {
    // 强引用
    String str = "张三";
    // 软引用
    SoftReference<String> stringSoftReference = new SoftReference<>(str);
    // 弱引用
    WeakReference<String> weakReference = new WeakReference<>(str);

    // 虚引用
    ReferenceQueue<String> queue = new ReferenceQueue<String>();
    PhantomReference<String> phantomReference = new PhantomReference<>(str, queue);
}

Java内存屏障

  • 内存屏障是让一个CPU处理单元中的内存状态对其它处理单元可见的一项技术。

作用

  • 阻止屏障两侧的指令重排序
  • 强制把写缓冲区/高速缓存中的脏数据等写回主内存,让缓存中相应的数据失效。

类型

  • 内存屏障影响的是同一个线程内的代码的执行顺序。
  • LoadLoad 屏障
  • LoadStore屏障
  • StoreStore屏障
  • StoreLoad屏障

JVM模块

  • 堆:包含实例化对象及数组等。

  • 栈:对象的应用变量在函数的栈内存分配。

  • 程序计数器:是一个寄存器,可以看作是代码行号指示器,类似于实际计算机里的PC,用于指示,跳转下一条需要执行的命令。

  • 本地方法栈:执行的是Native方法,为Native方法服务。在JVM规范中,没有对它的实现做具体规定。

  • 方法区:用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码数据等。

  • Jvm 知识详见博客:https://blog.csdn.net/qq_37248504/article/details/119088250?spm=1001.2014.3001.5501


volatile关键字

  • volatile变量的写会立即刷新到主存。

  • volatile变量的读会读主存中的新值。

  • volatile关键字就是提示JVM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值