Java知识小结

目录

一、为什么非静态方法不能访问静态方法、静态成员?

二、普通代码块、静态代码块、构造器(constructor)的执行顺序

三、synchronized锁的是什么

四、synchronized关键字和volatile关键字的区别

五、Java中的类加载器

   1、概念

   2、JVM中的类加载器的分类:

六、关于Java内存局域

七、Object类中的方法有哪些

    1.toString()     

    2.wait()、wait(long timeout)、wait(long timeout,int naos)     

    3.notify()和notifyAll()     

    4.finalize()

    5.equals()

    6.hashCode()

    7.getClass()

    8.clone()

八、Integer对象的方法

九、垃圾回收机制

1.概念

2.System.gc的作用

十、Java一个源程序只能有一个public类存在,且类名与文件名相同。

十一、在java的多态调用中,new的是哪一个类就是调用的哪个类的方法。

十二、jdk1.8中,java 抽象类和接口的区别

1.相同点:

2. 抽象类的特点:

3. 接口的特点:


一、为什么非静态方法不能访问静态方法、静态成员?

        因为静态方法、静态成员是随着类加载而加载的,而非静态方法、非静态成员是在类创建(new)好过后,才会有的。(加载时间不一样)

        静态方法、静态成员的生命周期比非静态的要早,消亡的时间要晚。

二、普通代码块、静态代码块、构造器(constructor)的执行顺序

        静态代码块>普通代码块>构造器(constructor)

        因为静态代码块是随着类的加载而加载的,普通代码块在创建对象时才会被加载,构造器执行之后,代表对象真正地创建成功,是最后一步。

三、synchronized锁的是什么

        加锁实际上就是在锁对象的对象头中写入当前线程id,每个线程要想调用这个同步方法,都会先去锁对象的对象头看看当前线程id是不是自己的。

        对于静态方法来说,锁的是T.class(T为类名),这个类的字节码文件;非静态方法锁的是this,也就是类的实例对象;代码块锁的是括号里的对象。

注意:synchronized是可重入锁。也就是说当线程访问对象的同步方法时,在调用其他同步方法时无需再去获取其访问权。

四、synchronized关键字和volatile关键字的区别

  • volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块。synchronized关键字在JavaSE1.6后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其他各种优化之后执行效率有了显著提升,实际开发中使用synchronized关键字的场景还是更多一些。
  • 多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞
  • volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都可以保证。
  • volatile关键字主要用于解决变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性。

五、Java中的类加载器

   1、概念

             Java类加载器是Java运行时环境的一部分,负责动态加载Java类到JVM的内存空间中。每个Java类必须由某个类加载器装入到内存中。每个类加载器都有一个父类加载器(BootStrap引导类加载器没有)。

   2、JVM中的类加载器的分类:

        (1)、Bootstrap ClassLoader :引导类加载器。这个加载器很特殊,它不是JAVA类,因此它不需要被别人加载,它嵌套在JVM内核里,也就是说JVM启动的时候BootStrap就启动了,它是C++写的二进制代码,可以加载别的类。这也是为什么System.class.getClassLoader()结果为null的原因,因为它不是JAVA类,所以它的引用返回null。负责加载核心Java库,存储在<JAVA_HOME>/jre/lib/rt.jar   

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

        (3)、System ClassLoader:系统类加载器。主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作。

        (4)、User Custom ClassLoader:用户自定义类加载器(java.lang.ClassLoader的子类)
在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性。

六、关于Java内存局域

        (1)、程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器(偏移地址),Java编译过程中产生的字节码有点类似编译原理的指令,程序计数器的内存空间存储的是当前执行的字节码的偏移地址,每一个线程都有一个独立的程序计数器(程序计数器的内存空间是线程私有的),因为当执行语句时,改变的是程序计数器的内存空间,因此它不会发生内存溢出 ,并且程序计数器是jvm虚拟机规范中唯一一个没有规定 OutOfMemoryError 异常 的区域;

        (2)、java虚拟机栈:线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会床创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。  没有类信息,类信息是在方法区中;

        (3)、java堆:对于绝大多数应用来说,这块区域是 JVM 所管理的内存中最大的一块。线程共享,主要是存放对象实例和数组;

        (4)、方法区:属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

七、Object类中的方法有哪些

    1.toString()     

        返回一个String类型的字符串,用于描述当前对象的信息。

    2.wait()、wait(long timeout)、wait(long timeout,int naos)     

       注意: 在多线程环境下才会使用wait()

        wait()的作用:让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒并进入“就绪状态”。
        wait(long timeout)的作用:让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的notify()方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒并进入“就绪状态”。

    3.notify()和notifyAll()     

        notify()方法:针对多线程,在wait()方法后面使用,用于唤醒该对象等待的某个线程

        notifyAll()方法:针对多线程,在wait()方法后面使用,用于唤醒该对象等待的所有线程

    4.finalize()

        java允许在类中定义一个名为finalize()的方法。

        它的工作原理是:在垃圾回收器准备好释放对象占用的存储空间前,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。        

    5.equals()

        Object中的equals()方法是直接用来判断两个对象指向的内存空间是不是同一块。如果是同一块内存地址,则返回true。

    6.hashCode()

        作用:返回字符串的哈希码值,用于判断两个对象的地址是不是同一个。

注意:1、如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。 
           2、如果两个对象不equals,他们的hashcode有可能相等。 
           3、如果两个对象hashcode相等,他们不一定equals。 
           4、如果两个对象hashcode不相等,他们一定不equals。 

    7.getClass()

        返回Object运行时的类,不可重写,要调用的话,一般和getName()联合使用,如getClass().getName();

    8.clone()

        通过clone方法复制一个对象。克隆又分为浅克隆、深克隆。

  • 浅克隆:原对象和克隆对象不同,但对象内的成员引用相同
  • 深克隆:原对象和克隆对象不同,且对象内的成员引用也不同

八、Integer对象的方法

        parseInt(): 把String变成int的基础数据类型;

public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s,10);
    }

        valueOf(): 把String转化成Integer对象类型;

public static Integer valueOf(String s) throws NumberFormatException {
        return Integer.valueOf(parseInt(s, 10));
    }

        intValue(): 把Integer对象类型转化成int的基础数据类型。

 public int intValue() {
        return value;
    }

九、垃圾回收机制

1.概念

        在java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫描那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

      当垃圾回收唤起释放无用对象时,会先调用该对象的finalize()方法。finalize()方法是在对象被当成垃圾从内存中释放前被调用,而不是在对象变成垃圾前被调用,垃圾回收器的启用不由程序员控制,也无规律可循,无法保证每个对象的finalize()方法最终都会被调用。

        finalize()方法是在java.lang.Object中实现的(Object类中的方法),在我们自定义的类中,可以被覆盖。但一般在最后要调用父类的finalize()方法来清除对象所使用的所有资源。

注意:并不是程序结束的时候就进行垃圾回收,垃圾回收的时间是不确定的。

2.System.gc的作用

        Java垃圾回收机制的执行的偶然性有时候也会给程序带来麻烦,如果在一个对象成为垃圾时需要马上释放,或者程序在某个时间内产生大量的垃圾时,希望能有一个人工干预的方法。Java提供了一个System.gc方法,使用这个方法可以强制启动垃圾回收器回收垃圾。 

十、Java一个源程序只能有一个public类存在,且类名与文件名相同。

        Java程序是从main方法开始执行的,public为类加载器提供入口,然后找到public类中的main方法开始执行。如果存在多个public类,程序将不知道该从哪里执行。

注意:内部类可以是public的,因为内部类是作为外部类的成员存在的

 当有多个public类存在时,会报错,提示你让另一个类不为public

当去除其中一个public后,就没有报错了。 

在内部类中可以有多个public类 。 

十一、在java的多态调用中,new的是哪一个类就是调用的哪个类的方法。

        重写时,父类被覆盖的方法是否是static的,若为static,不是根据new的类型调用,此时调用的是父类方法,若为普通方法,则是根据new的类型调用

public class Test {
    // 父亲类
    public static class Father{
        //普通方法
        public void say() {
            System.out.println("father");
        }
        //静态方法
        public static void action() {
            System.out.println("爸爸打儿子!");
        }

    }

    //儿子类
    public static class Son extends Father{
        //普通方法
        public void say() {
            System.out.println("son");
        }
        //静态方法
        public static void action() {
            System.out.println("别打");
        }
    }
    public static void main(String[] args) {
        Father f = new Son();
        f.say();
        f.action();
    }
}

输出结果:son
                 爸爸打儿子!

十二、jdk1.8中,java 抽象类和接口的区别

1.相同点:

  • 都不能被实例化
  • 接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。

2. 抽象类的特点:

  • 抽象类中可以有构造方法。
  • 抽象类中可以存在普通属性、方法、静态属性和方法。
  • 抽象类中可以存在抽象方法。
  • 如果一个类中有抽象方法,那么当前类一定是抽象类;但是抽象类中不一定有抽象方法。
  • 抽象类中的抽象方法,需要有子类实现。如果子类不实现,子类则需要定义为抽象的。

3. 接口的特点:

  • 接口只有方法的声明,没有方法的实现,java 1.8中可以定义static、default方法体。
  • 在接口中只有常量,因为定义的变量,在编译的时候都会默认加上public static final。
  • 在接口中的方法中,永远都被public修饰。
  • 接口中没有构造方法,也不能实例化接口对象。
  • 接口可以实现多继承。
  • 接口中定义的方法都需要实现类来实现(除static和default方法),如果实现类不能实现接口中的所有方法,实现类则应定义为抽象类。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值