java特殊要点

基础知识点

java关键字

abstract	表明类或者成员方法具有抽象属性
assert	断言,用来进行程序调试
boolean	基本数据类型之一,声明布尔类型的关键字
break	提前跳出一个块
byte	基本数据类型之一,字节类型
case	用在switch语句之中,表示其中的一个分支
catch	用在异常处理中,用来捕捉异常
char	基本数据类型之一,字符类型
class	声明一个类
const	保留关键字,没有具体含义
continue	回到一个块的开始处
default	默认,例如,用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现
do	用在do-while循环结构中
double	基本数据类型之一,双精度浮点数类型
else	用在条件语句中,表明当条件不成立时的分支
enum	枚举
extends	表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口
final	用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量
finally	用于处理异常情况,用来声明一个基本肯定会被执行到的语句块
float	基本数据类型之一,单精度浮点数类型
for	一种循环结构的引导词
goto	保留关键字,没有具体含义
if	条件语句的引导词
implements	表明一个类实现了给定的接口
import	表明要访问指定的类或包
instanceof	用来测试一个对象是否是指定类型的实例对象
int	基本数据类型之一,整数类型
interface	接口
long	基本数据类型之一,长整数类型
native	用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的
new	用来创建新实例对象
packageprivate	一种访问控制方式:私用模式
protected	一种访问控制方式:保护模式
public	一种访问控制方式:共用模式
return	从成员方法中返回数据
short	基本数据类型之一,短整数类型
static	表明具有静态属性
strictfp	用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范
super	表明当前对象的父类型的引用或者父类型的构造方法
switch	分支语句结构的引导词
synchronized	表明一段代码需要同步执行
this	指向当前实例对象的引用
throw	抛出一个异常
throws	声明在当前定义的成员方法中所有需要抛出的异常
transient	声明不用序列化的成员域
try	尝试一个可能抛出异常的程序块
void	声明当前成员方法没有返回值
volatile	表明两个或者多个变量必须同步地发生变化
while	用在循环结构中

final

解读:final关键字是java的一个修饰符,可以用来声明类,方法,属性。

被final修饰的类,方法,属性,具有以下特点:
1)final修饰类,该类不可被继承

2)final修饰方法,该方法不可被重写,可以被继承和重载

3)final修饰属性,该属性为常量,不可改变

如何理解equals和hashcode?

现假设有对象A和B,如果A.equals(B)==true,那么对象A和对象B的对象内容相等,hashcode也相同。(hashcode相同对象不一定相同);

equals必须满足3个特性:对称性,自反性,一致性;
在重写equals方法时一定要重写hashcode方法;

equals和运算符双等号的区别
1)equals:父类的equals方法是用来比较方法两个对象的地址是否相等,String类的equals方法是用来比较两个字符串的内容是否相同。equals方法不能用于基本数据类型的变量,如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址,如果重写了equals,就看equals的具体实现规则

2)"==":如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象的地址值是否相等

先来一段代码测试一下:

package com.test;

import org.omg.CORBA.PRIVATE_MEMBER;

public class Test {
    public static void main(String[] args) {
        String s1 = "123";
        String s2 = "123";
        System.out.println(s1.equals(s2));
        System.out.println(s1 == s2);

        String s3 = new String("456");
        String s4 = new String("456");
        System.out.println(s3.equals(s4));
        System.out.println(s3 == s4);
    }
}
输出结果:
"C:\Program Files\Java\jdk1.8.0_212\bin\java.exe" "-javaagent:D:\JetBrains\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=54178:D:\JetBrains\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_212\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\rt.jar;F:\workspace\springtest\target\classes;D:\resp\org\springframework\spring-core\4.3.18.RELEASE\spring-core-4.3.18.RELEASE.jar;D:\resp\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\resp\org\springframework\spring-context\4.3.18.RELEASE\spring-context-4.3.18.RELEASE.jar;D:\resp\org\springframework\spring-aop\4.3.18.RELEASE\spring-aop-4.3.18.RELEASE.jar;D:\resp\org\springframework\spring-beans\4.3.18.RELEASE\spring-beans-4.3.18.RELEASE.jar;D:\resp\org\springframework\spring-expression\4.3.18.RELEASE\spring-expression-4.3.18.RELEASE.jar;D:\resp\org\springframework\spring-jdbc\4.3.18.RELEASE\spring-jdbc-4.3.18.RELEASE.jar;D:\resp\org\springframework\spring-tx\4.3.18.RELEASE\spring-tx-4.3.18.RELEASE.jar" com.test.Test
true
true
true
false

Process finished with exit code 0

再来看一个例子,关于equals方法重写和不重写比较的差异:

package com.test.main;

public enum EnumA {
    NAME(1,"1");

    private int code;
    private String name;

    EnumA(int code, String name) {
        this.code = code;
        this.name = name;
    }
}


package com.test.main;

public class Test {
    public static void main(String[] args) {
        TestB testB = new TestB();
        boolean result = EnumA.NAME.equals(testB.getEnum());
        System.out.println(EnumA.NAME.hashCode());//枚举EnumA的hashcode
        System.out.println(testB.getEnum().hashCode());//TestB的hascode
        System.out.println(result);
        //因为Enum默认重写了equals和hashcode方法,内部比较的也是地址,但是枚举类是静态类,对象是放在一个共享空间,所以==比较的结果地址是一样的,返回true
        // 打印结果:
        //1977594184
        //1977594184
        //true

        TestB testb2 = new TestB();
        TestB testb3 = new TestB();
        boolean result2 = testb2.equals(testb3);
        System.out.println(testb2.hashCode());//testb2的hashcode
        System.out.println(testb3.hashCode());//testb3的hashcode
        System.out.println(result2);
        //因为TestB没有重写equals和hashcode方法,所以equals比较的是对象的引用地址,因为用的是Object父类的equals方法,查看源码可以知道比较的是引用地址
        // 打印结果:
        //821045869
        //1735488308
        //false

    }
}

&和&&的区别

&和&&运算结果是一致的,他们的区别在于:

if(a==1 & b ==2){};//这里两边都会判断一遍

if(a1 && b2){};//这里只有当a1成立才会接着判断b2,如果a1不成立,那么后面的b2不会去判断。

重载和重写的区别

两者都为java多态的体现;
重载:方法名相当,参数的顺序,类型,个数不同,返回类型可以不同;
PS:为什么不能根据返回类型不同来区分重载?
answer:因为有返回值的方法可以选择不接收,当调用两个方法名一样的方法,其他相同,一个有返回值,一个没有返回值的时候,java编译器认为方法重复,不知道调用哪个;

重写:方法名和参数完全一致,但构造方法,final和static修饰的方法不能被重写;访问权限不能比父类低

java是值传递和引用传递

这个问题深究起来也是非常复杂的,这里简单的理解一下,java只有值传递;
当一个对象实例被当做参数传递到其他方法当中时,参数的值就是该对象的内存地址,该内存地址指向的堆内容是可以被改变的,也就是说对象当做参数传递,可以改变对象的内容。

理解抽象类和接口

抽象类:abstract class
接口:interface

简单的理解:abstract 用来定义一个抽象类,而interface用来定义接口;
abstract不能实例化;
abstract类中可以有普通成员方法,也可以有abstract 修饰的抽象方法;
abstract定义的abstract方法在子类必须有实现;
abstract不能和static,native,synchronized同时使用,因为抽象类要有实现,可static不能被实现,native和synchronized都和方法实现相关;

interface接口类中所有的的方法都没有方法体,都是抽象的,都必须在实现类中进行实现;
interface接口类中的所有成员变量都默认为public static final;

一个类可以实现N个接口,但是只能继承一个父类;

public,protected,default,private 访问区别

在这里插入图片描述

hashmap和hashtable的区别

hashmap允许key和value都为null,为非线程安全;
hashtable不允许,线程安全;
看一下源码:
Hashtable.class:

public synchronized V put(K var1, V var2) {
        if (var2 == null) {
            throw new NullPointerException();
        } else {
            Hashtable.Entry[] var3 = this.table;
            int var4 = var1.hashCode();
            int var5 = (var4 & 2147483647) % var3.length;

            for(Hashtable.Entry var6 = var3[var5]; var6 != null; var6 = var6.next) {
                if (var6.hash == var4 && var6.key.equals(var1)) {
                    Object var7 = var6.value;
                    var6.value = var2;
                    return var7;
                }
            }

            this.addEntry(var4, var1, var2, var5);
            return null;
        }
    }
    hashtable用了syncchronized修饰,表示线程安全;

再来看一下hashmap的源码:

public V put(K var1, V var2) {
        return this.putVal(hash(var1), var1, var2, false, true);
    }

    final V putVal(int var1, K var2, V var3, boolean var4, boolean var5) {
        HashMap.Node[] var6;
        int var8;
        if ((var6 = this.table) == null || (var8 = var6.length) == 0) {
            var8 = (var6 = this.resize()).length;
        }

        Object var7;
        int var9;
        if ((var7 = var6[var9 = var8 - 1 & var1]) == null) {
            var6[var9] = this.newNode(var1, var2, var3, (HashMap.Node)null);
        } else {
            Object var10;
            Object var11;
            if (((HashMap.Node)var7).hash == var1 && ((var11 = ((HashMap.Node)var7).key) == var2 || var2 != null && var2.equals(var11))) {
                var10 = var7;
            } else if (var7 instanceof HashMap.TreeNode) {
                var10 = ((HashMap.TreeNode)var7).putTreeVal(this, var6, var1, var2, var3);
            } else {
                int var12 = 0;

                while(true) {
                    if ((var10 = ((HashMap.Node)var7).next) == null) {
                        ((HashMap.Node)var7).next = this.newNode(var1, var2, var3, (HashMap.Node)null);
                        if (var12 >= 7) {
                            this.treeifyBin(var6, var1);
                        }
                        break;
                    }

                    if (((HashMap.Node)var10).hash == var1 && ((var11 = ((HashMap.Node)var10).key) == var2 || var2 != null && var2.equals(var11))) {
                        break;
                    }

                    var7 = var10;
                    ++var12;
                }
            }

hashmap没有相关修饰,为非线程安全,高并发下,put可能会发生哈希冲突;ConcurrentHashMap为线程安全的map集合类,都属于java对象;

先写到这里吧,太晚了,睡了睡了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值