Java基础知识复习汇总

 

hashCode()方法和equals()方法的作用其实是一样的,在Java里都是用来对比两个对象是否相等一致。

那么equals()既然已实现比的功能了,为什么还要hashCode()呢?因为重写的equals()里一般比较的比较全面比较复杂,这样效率就比低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。

那么hashCode()既然效率这么高为什么还要equals()呢 因为hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,

所以我们可以得出:

1.equals()相等的两个对象他们的hashCode()肯定相等,也就是用equals()对比是绝对可靠的。

2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。

所有对于需要大量并且快速的对比的话如果都用equals()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equals(),如果equals()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!

 



HashSet内部使用Map保存数据,即将HashSet的数据作为Map的key值保存,这也是HashSet中元素不能重复的原因。而Map中保存key值前,会去判断当前Map中是否含有该key对象,内部是先通过key的hashCode,确定有相同的hashCode之后,再通过equals方法判断是否相同。

 

 

 

public class TestObj{ 
    public static void main(String[] args){
        Object o=new Object(){
            public boolean equals(Object obj){
                return true;
            }
        }; 
        System.out.println(o.equals(“Fred”));
    }

本题涉及匿名内部类、多态和覆盖三个知识点。

语句Object o=new Object(){ public boolean equals(Object obj){ return true; } };

创建了一个匿名内部类,并将所创建的匿名对象赋给 Object (多态:子类对象赋给超类引用)。同时,该匿名内部类重写了 Object 类的 equals 方法。

在执行语句o.equals(“Fred”)时,根据多态及覆盖原则,会调用匿名内部类重写后的 equals 方法。

 

 

 

根据以下代码段,下列说法中正确的是(    )。

public class Parent {

    private void m1(){}

    void m2(){}

    protected void m3(){}

    public static void m4(){}

}

A 子类中一定能够继承和覆盖Parent类的m1方法
B 子类中一定能够继承和覆盖Parent类的m2方法
C 子类中一定能够继承和覆盖Parent类的m3方法
D 子类中一定能够继承和覆盖Parent类的m4方法

解读:

通过继承,子类可以拥有所有父类对其可见的方法和域

A.私有方法只能在本类中可见,故不能继承,A错误

B.缺省访问修饰符只在本包中可见,在外包中不可见,B错误

C.保护修饰符凡是继承自该类的子类都能访问,当然可被继承覆盖;C正确

D.static修饰的成员属于类成员,父类字段或方法只能被子类同名字段或方法遮蔽,不能被继承覆盖,D错误。

子父类存在同名静态函数访问的是父类。

 

 

 

package xufeng;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Test {

	public static void main(String[] args) {
		
		Collection<?>[] collections = { new HashSet<String>(), new ArrayList<String>(),
				new HashMap<String, String>().values() };
		
		Super subToSuper = new Sub();
		
		for (Collection<?> collection : collections) {
			System.out.println(subToSuper.getType(collection));
		}
	}

	abstract static class Super {
		public static String getType(Collection<?> collection) {
			return "Super:collection";
		}

		public static String getType(List<?> list) {
			return "Super:list";
		}

		public String getType(ArrayList<?> list) {
			return "Super:arrayList";
		}

		public static String getType(Set<?> set) {
			return "Super:set";
		}

		public String getType(HashSet<?> set) {
			return "Super:hashSet";
		}
	}

	static class Sub extends Super {
		public static String getType(Collection<?> collection) {
			return "Sub";
		}
	}
}
运行结果:
A:
Sub:collection
Sub:collection
Sub:collection
B:
Sub:hashSet
Sub:arrayList
Sub:collection
C:
Super:collection
Super:collection
Super:collection
D:
Super:hashSet
Super:arrayList
Super:collection

答案解读:

C

运行结果:


重载,[静态分配]: 参数匹配看实参定义(等号)的左边。 所以本题都是调用collection

重写,[动态分派]: 调用谁的方法,看对象定义的右边。 本题是静态方法,并不是重写,而是属于子类独有的静态方法,又因为是向上转型,所以这时候只能访问父类与子类共有的属性,所以此时调用的是父类的方法。

静态属性和静态方法只是可以继承没有表现出多态性。
因为静态方法和静态属性没有采用动态绑定。
具体表现就是,
将子类实例向上转型则会调用到基类中的静态方法和属性,       
不转型就调用子类自身的静态方法和属性。
编译器不推荐通过实例去调用静态方法和属性,因为这种调用方式容易造成混淆。

 

以下哪种JAVA的变量表达式使得变量a和变量b具有相同的内存引用地址(  )

String a = "hello"; String b = "hello";
Integer a; Integer b = a;
int a = 1; Integer b = new Integer(1);
int a = 1; Integer b = 1;

内存引用地址,是指栈中存放的地址,来指向堆中的某个位置。
int 是基本类型,数据直接存放在栈中,不存在内存引用地址的说法
==
A对  指向常量池里的"hello"。
B对  题中没说声明的a是局部变量。
C错  int a =1;并不指向堆中,它只有值,没有引用地址,Integer b =new Integer(1);指向堆中地址为1的位置。
D错  原因同C

(1)int与Integer、new Integer()进行==比较时,结果永远为true

(2)Integer与new Integer()进行==比较时,结果永远为false

(3)Integer与Integer进行==比较时,看范围;在大于等于-128小于等于127的范围内为true,在此范围外为false。

 

 

对于构造方法,下列叙述正确的是( )。

A 构造方法的优先级一般比代码块低。
B 构造方法的返回类型只能是void型。
C 构造方法的主要作用是完成对类的对象的初始化工作。
D 一般在创建新对象时,系统会自动调用构造方法。

解析:

A:静态成员变量或静态代码块>main方法>非静态成员变量或非静态代码块>构造方法

B:think in java中提到构造器本身并没有任何返回值。

C: 构造方法的主要作用是完成对类的对象的初始化工作。

D: 一般在创建(new)新对象时,系统会自动调用构造方法。

 

构造方法没有返回值类型,也不写void

 

代码块:

分类:静态代码块和实例代码块

静态代码块:static修饰的代码块,在类加载时执行,且只执行一次。因为类就加载一次了。

实例代码块:没有static修饰的代码块,创建对象时执行,每创建一次对象加载一次。

实例代码块在执行构造方法之前执行。所以优先级高于构造方法。

 

java程序初始化顺序:

父类静态变量,父类静态代码块(只执行一次),

子类静态变量,子类静态代码块(只执行一次),

父类非静态变量,父类非静态代码块,父类构造函数,

子类非静态变量,子类非静态代码块,子类构造函数

归纳一下:

父静子静,父实例子实例。

先变量再代码块,最后再构造

 

 

 

public class NameList
{
    private List names = new ArrayList();
    public synchronized void add(String name)
    {
        names.add(name);
    }
    public synchronized void printAll()     {
        for (int i = 0; i < names.size(); i++)
        {
            System.out.print(names.get(i) + ””);
        }
    }

    public static void main(String[]args)
    {
        final NameList sl = new NameList();
        for (int i = 0; i < 2; i++)
        {
            new Thread()
            {
                public void run()
                {
                    sl.add(“A”);
                    sl.add(“B”);
                    sl.add(“C”);
                    sl.printAll();
                }
            } .start();
        }
    }
}

链接:https://www.nowcoder.com/questionTerminal/25deb8d21e7d442e86c90302d6e03133
来源:牛客网
 

Which two statements are true if this class is compiled and run?

 

  • An exception may be thrown at runtime.
  • The code may run with no output, without exiting.
  • The code may run with no output, exiting normally(正常地).
  • The code may rum with output “A B A B C C “, then exit.
  • The code may rum with output “A B C A B C A B C “, then exit.
  • The code may ruin with output “A A A B C A B C C “, then exit.
  • The code may ruin with output “A B C A A B C A B C “, then exit.

解析:EG

分2段打印。

第2个部分线程一定是最后6个。

起始部分和余下的第1部分一定是重复的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值