java基础1

    技术2022-07-12  84

    1)重写equals方法的时候为什么需要重写hashcode?

     

    Java的object中equals的实现:

    public boolean equals(Object obj) { return (this == obj); }

    可以看到是用来比较两个对象的内存地址是否相等。

    hashCode方法是本地方法,用于计算出对象的一个散列值,用于判断在集合中对象是否重复的关键。

    在源码注解中大致讲述看:当我们将equals方法重写后有必要将hashCode方法也重写,这样做才能保证不违背hashCode方法中“相同对象必须有相同哈希值”的约定。

    作者定义hashCode:将对象的地址值映射为integer类型的哈希值。

    一个对象多次调用它的hashCode方法,应当返回相同的integer(哈希值)。两个对象如果通过equals方法判定为相等,那么就应当返回相同integer。两个地址值不相等的对象调用hashCode方法不要求返回不相等的integer,但是要求拥有两个不相等integer的对象必须是不同对象。

    总的来说:

    相同的对象必然导致相同的哈希值。不同的哈希值必然是由不同对象导致的。

    在String源码中比较两个对象除了在两个对象的内存地址相等的时候返回true,还会在比较其对应的字符都相等的时候也返回true。所以现在可以得到“因为必须保证重写后的equals方法认定相同的两个对象拥有相同的哈希值”。同时我们顺便得出了一个结论:“hashCode方法的重写原则就是保证equals方法认定为相同的两个对象拥有相同的哈希值”。

    同时我们从HashMap中分析(key对象必须重写equals和hashCode)

    无论是 put 还是 get 的时候,都需要得到key的哈希值,去定位key的数组下标;在 get 的时候,需要调用equals方法比较是否有相等的key存储过。 User user1=new User("name"); User user2=new User("name"); HashMap<User, String> hashmap=new HashMap<User,String>(); hashmap.put(user1, "value1"); String str=hashmap.get(user2); System.out.println("输出结果:"+str);//null

    上面的例子都未重写equals,所以在查找user2的时候使用的object的equals,比较的是地址,而user1和user2的地址肯定不同,所以找不到。(即使重写了equals而没有重写hashCode也不一定能找的,应为他们的地址不同所以找到的数组下标也不一定相同

    2)八种基本类型

    整型:byte(8bit)short(16bit)int(32bit)long(64bit)

    浮点型:float(32bit)double(64bit)

    字符型:char(2字节,16bit)

    布尔型:boolean(为true和false,默认值为false)

    3)键盘输入(脑抽插播)

    import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner sc = new Scanner(System.in); String name = sc.nextLine(); int age = sc.nextInt(); float f = sc.nextFloat(); } }

    4)String底层的数组使用的是final修饰,即如 str1+str2是new了一个String

    可以使用stringBuild和stringBuffer的

    《Think in Java》中,描述

           HashTable和HashMap区别一样,就是因为HashTable支持线程同步、保证线程安全而导致的性能下降。

      HashTable是线程安全的,很多方法都是synchronized方法。

      HashMap不是线程安全的,但在单线程程序中的性能比HashTable要高。

    而现在StringBuffer和StringBuilder类的区别也在于此,StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。 

    5)抽象类和接口的区别

    抽象类可以有抽象方法和非抽象方法而接口值能有抽象方法(默认修饰)(但在JDK1.8中接口可以有default和static方法)。

    抽象类只能单继承(extends),而接口可以多实现(implements)。

    抽象类中的成员可以是private、默认、protected、public的,而接口中的成员全都是public的。

    接口只能由static final变量,而抽象类可以有普通变量(因为防止多实现不统一的改变变量,而抽象类是单继承的所以没问题)。

    6)普通类和抽象类的区别

    抽象类不能被实例化。

    抽象类中抽象方法不需要实现。

    (含有抽象方法的类必须声明为抽象类abstract class 类名,接口inteface类名)。

    7)访问修饰符

    public《-protected《-default《-private

    1234      123             12            1

    1其他包 2当前包 3子类 4当前类

    8)自动装箱和自动拆箱

    //自动装箱 Integer total = 99;//调用valueOf() //自动拆箱 int totalprim = total;//调用intValue,对应别的是xxxValue()

    9)&与&&

    &&之所以称为短路运算,是因为左边为false时右边直接跳过了返回false,

    if(x==33 & ++y>0) y会增长,if(x==33 && ++y>0)不会增长,(&&使用时需要注意顺序,比如比较为null和空字符串时)

    &还可以用作位运算符,只有对应的两个二进位都为1时,结果位才为1。

    10)JDK、JRE、JVM

    JDK是java开发工具包( JDK包含了JRE,同时还包括java源码的编译器javac、监控工具jconsole、分析工具jvisualvm等)

    JRE是java运行时环境(用户只需要有jre即可运行程序),java虚拟机(JVM),java基础类库

    JVM Java虚拟机,加载.class并运行.class

    11)final和static

    static表示静态或全局,被修饰的属性和方法属于类,可以用类名.静态属性 / 方法名 访问

    static属性:静态变量或者叫全局变量,类变量,被修饰的属性和方法属于类,可以用类名.【静态属性 |方法名】 访问

    static 修饰的代码块表示静态代码块,当 Java 虚拟机(JVM)加载类时,就会执行该代码块,只会被执行一次(单例模式可以使用

    static方法必须被实现不能是抽象的,而且不能被重写

    static不能以任何方式调用this和super和非静态方法,因为在类加载时,对象未初始化前已经把类的static加载到了jvm的方法区(此时如果没被final则基本数据类型会被赋值为默认值,0,false。。。,特别的,如static final int  init = 100,则会被赋值为100),所以不知道非静态方法

     

    final修饰属性:基本数据类型-值不能改变,对象-引用地址不能变但是对象内容课可以改变

    final修饰方法:方法不能被重写

    final修饰类:类不能被继承,final 类中的方法默认是 final 的

     

    结!

    不写了困了,睡觉前刷一题简单题:

    题目描述

    地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

    import java.util.LinkedList; import java.util.Queue; class Solution { public int movingCount(int threshold, int rows, int cols) { if(threshold < 0) return 0; int[] dp = new int[(1+rows)*(1+cols)]; dp[0] = 1; int[][] kunsile = {{1,0},{-1,0},{0,1},{0,-1}}; Queue<Integer> queue = new LinkedList<Integer>(); queue.add(0); int sum = 1; int w; while(queue.peek() != null){ w = queue.poll(); int l = w/cols; int r = w%cols; for(int i = 0; i < kunsile.length; i++){ int ll = l + kunsile[i][0]; int rr = r + kunsile[i][1]; if(ll<0 || rows <= ll || rr < 0 || cols <= rr){ continue; } if(dfs(ll,rr,threshold) && dp[ll*cols+rr]==0){ dp[ll*cols+rr] = 1; sum++; queue.add(ll*cols+rr); } } } return sum; } public boolean dfs(int ll, int rr, int threshold){ int sum = 0; while(ll != 0){ sum += ll; ll/=10; } while(rr != 0){ sum += rr; rr/=10; } return sum > threshold ? false :true; } };

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    Processed: 0.010, SQL: 9