Java接口与抽象(学习笔记)

来源:互联网 发布:excel重复数据高亮 编辑:程序博客网 时间:2024/06/05 00:56

一、== 和 equals方法

当使用==来判断两个变量是否相等时,如果两个变量是基本类型变量,且都是数值类型(不一定要求数据类型严格相同),则只要两个变量的值相等,就返回true。

但对于两个引用类型变量,只有他们指向同一个对象时,==判断才会返回true。==不可以用来比较两个类型上没有父子关系的对象。

public class EqualTest

{

         publicstatic void main(String args[]){

                   inti = 65;

                   floatf = 65.0f;

                   charc = 'A';

                   System.out.println("65和 65.0f 的比较结果 " + (i == f));

                   System.out.println("65和 'A' 的比较结果 " + (i == c));

                   System.out.println("65.0f和 'A' 的比较结果 " + (f == c));

 

                   Stringstr1 = new String("hello");

                   Stringstr2 = new String("hello");

                   System.out.println("str1== str2 ? " + (str1 == str2));

                   System.out.println("str1equals str2 ? " + str1.equals(str2));

                  

                   //下面的语句在编译时发生错误

                   //System.out.println("hello"== new EqualTest());

                   Strings1 = "疯狂Java";

                   Strings2 = "疯狂";

                   Strings3 = "Java";

                   Strings4 = "疯狂" + "Java";

                   Strings5 = "疯"+"狂"+"Java";

                   Strings6 = s2 + s3;

                   Strings7 = new String("疯狂Java");

                   System.out.println("\n\n"+ (s1==s4));

                   System.out.println(s1==s5);

                   System.out.println(s1==s6);

                   System.out.println(s1==s7);

         }

}

 

String还有一个非常容易迷惑的地方:

‘’hello”直接量和new String(“hello”);有什么区别呢?当直接使用形如”hello”的字符串直接量时,JVM将会使用常量池来管理这些字符串;当使用new String(“hello”);时,JVM将会先使用常量池来管理”hello”直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象将会被保存在堆内存中。换句话说,new String()一共产生了两个字符串对象。

 

 

二、单例类

见如下代码:

class Singleton

{

         //instance用来缓存曾经创建的实例对象。由于需要被get方法访问,所以需要static修饰符

         privatestatic Singleton instance;

         //使用private修饰,为了隐藏该构造器,不致以被其他类访问,从而创建多个对象

         privateSingleton(){}

         //(与外部的接口)调用该方法创建实例对象,因此用public修饰,但调用该方法时还没有对象,只能通过类调用,将该方法声明为类方法,因此用static修饰

         publicstatic Singleton getInstance(){

                   if(instance== null){instance = new Singleton();}

                   returninstance;

         }

}

 

public class SingletonTest

{

         publicstatic void main(String args[]){

                   Singletons1 = Singleton.getInstance();

                   Singletons2 = Singleton.getInstance();

                   System.out.println(s1==s2);

         }

}

 

小提示:类变量和实例变量有什么区别?类变量是所有实例共同拥有,只要一个改变,则所有对象的该变量都随着改变,类变量由static关键字声明,系统为每个类变量分配一次存储空间。实例变量是类实例化后,系统为其创建的一个类的实例变量拷贝,每个实例拥有一个实例变量,实例变量是对象私有的,某一对象将其改变,不影响其他对象。

 

三、final修饰符

当使用final修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。但对于引用类型而言,它保存的仅仅是一个引用,final只保证这个引用类型变量所引用的地址不会改变,即一直引用一个对象,但这个对象的内容完全可以发生改变。例如:

Final int[] iArr = {1,2,3,4,5};

iArr[2] = 100; //这是合法的

iArr = null;//这是非法的

对于实例变量也如此。

 

Final修饰的方法不能被重写,final修饰的类没有子类。

 

四、抽象类

抽象方法和抽象类必须使用abstract修饰符来定义。有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法。抽象方法是指只有方法名,没有方法实现的方法。

 

抽象类不能被实例化,但抽象类里可以包含构造器,这儿的构造器并不是实例化时使用,而是提供给该抽象类的子类使用。

 

Private和abstract不能同时修饰方法(因为abstract修饰的方法必须被重写才有意义,private修饰的方法不能被继承,即不能被重写)。

Final和abstract永远不能同时使用(因为final类不能被继承,而abstract修饰的类必须被继承重写才有意义)。但内部类除外。

 

抽象类的作用:从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性。

 

public abstract class Shape

{

         {System.out.println("执行Shape的初始化块");}

         privateString color;

         publicabstract double getPerimeter();

         publicabstract String getType();

 

         publicShape(){}

         publicShape(String color)

         {

                   System.out.println("执行Shape的构造器");

                   this.color= color;

         }

 

         publicvoid setColor(String color)

         {

                   this.color= color;

         }

         publicString getColor()

         {

                   returnthis.color;

         }

}

 

public class Triangle extends Shape

{

         privatedouble a;

         privatedouble b;

         privatedouble c;

         publicTriangle(String color, double a, double b, double c)

         {

                   super(color);

                   this.setSides(a,b,c);

         }

         publicvoid setSides(double a, double b, double c)

         {

                   if(a>= b+c || b >= a+c || c >= a+b)

                   {

                            System.out.println("三角形两边之和大于第三 边");

                            return;

                   }

                   this.a= a;

                   this.b= b;

                   this.c= c;

         }

         publicdouble getPerimeter()

         {

                   returna+b+c;

         }

         publicString getType()

         {

                   returngetColor() + "三角形";

         }

}

 

public class Circle extends Shape

{

         privatedouble radius;

 

         publicCircle(String color, double radius)

         {

                   super(color);

                   this.radius= radius;

         }

         publicdouble getPerimeter()

         {

                   returnMath.PI*radius*2;

         }

         publicString getType()

         {

                   returngetColor() + "圆形";

         }

}

 

public class ShapeTest

{

         publicstatic void main(String args[])

         {

                   Shapet = new Triangle("白色",3,4,5);

                   Shapec = new Circle("红色", 3);

                   System.out.println(t.getType());

                   System.out.println(t.getPerimeter());

                   System.out.println(c.getType());

                   System.out.println(c.getPerimeter());

         }

}

 

另一个例子:

public abstract class SpeedMeter

{

         privatedouble trunRate;

         publicabstract double getRadius();

         publicvoid setTrunRate(double trunRate)

         {

                   this.trunRate= trunRate;

         }

         publicdouble getSpeed()

         {

                   return2 * Math.PI * getRadius() * trunRate;

         }

}

 

public class CarSpeedMeter extendsSpeedMeter

{

         publicdouble getRadius()

         {

                   return0.28;

         }

 

         publicstatic void main(String args[])

         {

                   CarSpeedMetercar = new CarSpeedMeter();

                   car.setTrunRate(15);

                   System.out.println(car.getSpeed());

         }

}

五、接口

由于接口定义的是一种规范,因此接口里不能包含构造器和初始化块定义。接口里可以包含成员变量(只能是静态常亮)、方法(只能是抽象方法、类方法、默认方法)、内部类。接口里的所有成员都是public访问权限。

 

在接口中定义成员变量时,不管是否使用public static final来修饰,接口里的成员变量总是使用这三个修饰符(即int MAX = 50; 和 public static final int MAX = 50 ;的写法完全一样)。接口里定义的成员变量只能在定义时指定默认值。

 

Java8允许在接口中定义类方法和默认方法(有方法体),访问权限都是public。类方法必须用static修饰,默认方法必须用default修饰。由于默认方法没有static修饰,所以不能直接使用接口来调用,需要使用接口的实现类的实例来调用。而类方法可以直接使用接口调用。

 

六、抽象与接口

接口体现的是一种规范,一种标准。类似于整个系统的“总纲”,制定了系统各个模块应该遵循的标准,一旦接口改变,对整系统的影响是辐射式的。

 

抽象体现的是一种模板设计模式。抽象类可以被当成系统实现过程中的中间产品,这个中间产品已经实现了系统的部分功能,但这个产品依然不能当成最终产品。

相同点:

①  接口和抽象类都不能被实例化,他们都位于继承树的顶端,用于被其他类实现或继承;

②  接口和抽象类都可以包含抽象方法,实现接口或者继承抽象类的普通子类都必须实现这些抽象方法。

 

0 0
原创粉丝点击