java基础,
java基础,
1 . 关于equals()方法和hashcode()方法
相同的对象一定具有相同的hashcode(),不同的对象也有可能具有相同的hashcode(),产生hash碰撞
重载equals的时候,一定要(正确)重载hashCode
使得equals成立的时候,hashCode相等,也就是a.equals(b)->a.hashCode() == b.hashCode(),或者说此时,
equals是hashCode相等的充分条件,hashCode相等是equals的必要条件(从数学课上我们知道它的逆否命题:
hashCode不相等也不会equals),但是它的逆命题,hashCode相等一定equals以及否命题不equals时
hashCode不等都不成立。
所以,如果面试的时候,最好把hashCode与equals之间没有强制关系,以及根据(没有语法约束力的)规范的角度,
应当做到...这两层意思都说出来:
总结一下,equals()是对象相等性比较,hashCode()是计算对象的散列值,当然他们的依据是对象的属性。
对于equals,一般我们认为两个对象同类型并且所有属性相等的时候才是相等的,在类中必须改写equals,
因为Object类中的equals只是判断两个引用变量是否引用同一对象,如果不是引用同一对象,
即使两个对象的内容完全相同,也会返回false。当然,在类中改写这个equals时,你也可以只对部分属性进行比较,
只要这些属性相同就认为对象是相等的。
对于hashCode,只要是用在和哈希运算有关的地方,和equals一样,在你的类中也应该改写。
当然如果两个对象是完全相同的,那么他们的hashCode当然也是一样的,但是像前面所述,规则可以由你自己来定义,
因此两者之间并没有什么必然的联系。
当然,大多数情况下我们还是根据所有的属性来计算hashCode和进行相等性比较。
hashcode()方法将对象的内存地址进行hash运算,返回的是一个int型的hash值
2. static关键字
static关键字修饰成员变量,称为静态变量。静态变量被所有实例共享,可以使用类名.变量名访问
static关键字只能修饰成员变量,不能修饰局部变量
static修饰方法块,不用创建对象直接通过类名.方法名的方式来访问
package com.base.door;
public class Example {
static {
System.out.println("测试类的代码执行了");
}
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
}
}
class Person {
static String country;
static {
country = "china";
System.out.println("Person类中的静态代码被执行了");
}
}
虚拟机首先会加载类Example,在加载累的同时就会执行该类的静态代码块,紧接着调用main()方法,在该方法中创建两个Person对象,但是两次实例化的过程中,静态代码块只会执行一次。
什么是单例模式?
1. 构造方法私有化
2. 静态属性指向实例
3. public static的 getInstance方法,返回第二步的静态属性
3. 多态 父类变量引用不同的子类对象,多态解决方法同名问题,允许使用一个父类类型的变量来引用一个子类类型的对象,根据被引用子类的
不同,得到不同的运行结果
package com.base.door;
//定义接口Animal
interface Animal {
void shout();
}
//定义Cat泪腺Animal接口
class Cat implements Animal {
public void shout() {
System.out.println("喵喵......");
}
}
class Dog implements Animal{
public void shout(){
System.out.println("汪汪....");
}
}
public class Example02 {
public static void main(String[] args) {
Animal an1 = new Cat();
Animal an2 = new Dog();
animalShout(an1);
animalShout(an2);
}
//定义静态方法animalShout接受一个animal类型的输入
private static void animalShout(Animal an) {
an.shout();
}
}
但是不能通过父类变量调用子类的某些方法
package com.base.door;
//定义animal接口
interface Animal {
void shout();
}
//定义cat类实现animal接口
class Cat implements Animal {
public void shout() {
System.out.println("喵喵......");
}
void sleep(){
System.out.println("猫睡觉");
}
}
public class Example02 {
public static void main(String[] args) {
Cat cat = new Cat();
animalShout(cat);//调用animalShout()方法,cat作为参数传入
}
private static void animalShout(Animal animal) {
animal.shout();
animal.sleep();
}
}
animalShout()方法调用时传入了Cat类型的对象,而方法的参数类型为Animal类型,这便将Cat对象当作父类Animal类型使用,当编译器检测到
animal.sleep()时,发现Animal类没有定义sleep()方法,从而报错
这时我们在animalShout()方法中进行强转
private static void animalShout(Animal animal) {
Cat cat = (Cat) animal;
cat.shout();
cat.sleep();
}
但是强转可能出现类型错误,如Animal类型无法转化为Cat类型,像这样
package com.base.door;
//定义animal接口
interface Animal {
void shout();
}
//定义cat类实现animal接口
class Cat implements Animal {
public void shout() {
System.out.println("喵喵......");
}
void sleep(){
System.out.println("猫睡觉");
}
}
class Dog implements Animal {
public void shout() {
System.out.println("汪汪......");
}
}
public class Example02 {
public static void main(String[] args) {
Dog dog = new Dog();
animalShout(dog);//调用animalShout()方法,cat作为参数传入
}
//定义静态方法animalShout(),接受一个Animal类型的参数
private static void animalShout(Animal animal) {
Cat cat = (Cat) animal;
cat.shout();
cat.sleep();
}
}
//针对这种情况,java提供instanceod,判断一个对象是否为某个类(或者接口的实例或者子类实例)
对象(或者对象的引用变量) instanceod 类(或接口) 像这样
package com.base.door;
//定义animal接口
interface Animal {
void shout();
}
//定义cat类实现animal接口
class Cat implements Animal {
public void shout() {
System.out.println("喵喵......");
}
void sleep(){
System.out.println("猫睡觉");
}
}
class Dog implements Animal {
public void shout() {
System.out.println("汪汪......");
}
}
public class Example02 {
public static void main(String[] args) {
Dog dog = new Dog();
animalShout(dog);//调用animalShout()方法,cat作为参数传入
}
//定义静态方法animalShout(),接受一个Animal类型的参数
public static void animalShout(Animal animal) {
if(animal instanceof Cat){
Cat cat = (Cat) animal;
cat.shout();
cat.sleep();
}else{
System.out.println("this animal is not a cat");
}
}
}
由于传入的是Dog类型,所以打印
this animal is not a cat
4.关于String和StringBuffer类
4.1String类表示的字符串是常量,一旦创建后,内容和长度都是无法改变的。而StringBuffer表示字符容器,其内容和长度都可以修改。
在操作字符串时,如果该字符串仅用于表示数据类型,则使用String类即可,但是如果需要对字符串中的字符进行增删操作,
则使用StringBuffer类
4.2String覆盖Object类下的equals()方法,而StringBuffer类没有覆盖Object类的equals()方法
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.equals(s2));
StringBuffer sb1 = new StringBuffer("abc");
StringBuffer sb2 = new StringBuffer("abc");
System.out.println(sb1.equals(sb2));
结果分别是
4.3 String类对象可以用操作符+进行连接,而StringBuffer对象不能,具体示例如下
5. jdk7新特性 switch语句支持字符串类型
String week = "Friday";
switch (week) {
case "Monday":
System.out.println("今天是星期一");
break;
case "Friday": {
System.out.println("今天星期五");
}
6. 装饰者模式
package com.base.door;
class Car {
private String carName;
public Car(String carName) {
this.carName = carName;
}
public void show() {
System.out.println("我是" + carName + ",具有基本功能");
}
}
class RadarCar {
public Car myCar;
public RadarCar(Car myCar) {
this.myCar = myCar;
}
public void show() {
myCar.show();
System.out.println("具有倒车雷达功能");
}
}
public class Example06 {
public static void main(String[] args) {
Car benz = new Car("benz");
System.out.println("---------------包装前--------------");
benz.show();
RadarCar decoratedCar_benz = new RadarCar(benz);
System.out.println("---------------包装后--------------");
decoratedCar_benz.show();
}
}
当RadarCar对象调用收方法时,RaderCar包装后的对象不仅具有车的基本功能,也具有倒车雷达的功能
6.static关键字 只需将static关键字放在定义之前,就可以将字段或方法设定为static,例如下面的代码就生成了一个static字段,并对其进行了
初始化
class StaticTest {
static int i = 47;
}
现在即使你创建两StaticTest对象,StaticTest.i也只有一份存储空间,这两个对象共享一个i,下面的代码st1.i和st2.i指向同一存储空间
class StaticTest {
static int i = 47;
}
public class Test {
public static void main(String[] args) {
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
System.out.println(st1.i==st2.i);
}
}
这里既可以通过一个对象去定位它,st2.i,也可以通过类型将以引用,StaticTest.i++
static修饰方法和修饰变量相似
7.java编码风格
在java编程语言编码规定中,代码风格是这样的:类的首字母要大写;如果类名由几个单词组成,那么把他们并在一起(也就是说,不需要用
下划线分割名字),其中的每个内部单词都采用大些形式,如
class AllTheClolrOfTheRainboe{
}
这种风格有时候被称作驼峰风格。几乎所有的内容方法、字段以及对象引用名称等,公认的风格与类的风格一样,只是标识符的
第一个字母才用小写。详情参考阿里巴巴java规范手册
8 equals 方法和==比较,在object类,equals方法与==没有差别,重写的话看实现,==号在基本数据类型相当于比较数值是否相等,在对象比较时比较对象的地址。
看下列实例
public class Test {
public static void main(String[] args) {
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
}
}
比较对象的引用
比较对象的实际内容一般使用.equals()方法,由于integer类重写了.equals方法,返回true
public class Test {
public static void main(String[] args) {
Integer n1 = new Integer(47);
Integer n2 = new Integer(47);
System.out.println(n1.equals(n2));
}
}
equals方法中默认比较的是引用,除非在新类中重写.equals()方法
class Value {
int i;
}
public class Test {
public static void main(String[] args) {
Value n1 = new Value();
Value n2 = new Value();
n1.i = n2.i = 100;
System.out.println(n1.equals(n2));
}
}
由于未重写.equals方法,默认比较引用,引用不同,返回false
9.对象可能不被垃圾回收
垃圾回收并不等于析构
垃圾回收只与内存有关
10.
有如下一段程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
请问最后打印出来的是什么?()
正确答案: B 你的答案: B (正确)
2
3
4
5
解析
return i++, 先返回i,然后i+1;
第一次调用getNext()方法时,返回的是1,但此时i=2;
第二次调用 getNext()方法时,返回的是2,但此时i=3;
第三次调用 getNext()方法时,返回的是3,但此时i=4;
先返回,后自增改为++i先自增,后返回,结果4
相关文章
- 暂无相关文章
用户点评