作业day06

今天元宵节,祝大家元宵快乐。

Java面向对象又进一步理解了很多。Java的抽象类和接口有很多相似的地方也有很多不同的地方,总之,用法和目的也不尽相同。Java基本数据类型和它们的包装类有自动装箱和拆箱。Java对于不知道传入的数据类型可以用泛型,泛型类,泛型方法,泛型数组。

 

知识点及习题

 

5.Java支持的数据类型有哪些?什么是自动拆装箱?

Java语言支持的8中基本数据类型是:

byte

short

int

long

float

double

boolean

char

基本数据(Primitive)类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱,解包装称为拆箱)

代码如下:

 

//声明一个Integer对象

Integer num = 10;

//以上的声明就是用到了自动的装箱:解析为

Integer num = new Integer(10);以上就是一个很好的体现,因为10是属于基本数据类型的,原则上它是不能直接赋值给一个对象Integer的,但jdk1.5后你就可以进行这样的声明,这就是自动装箱的魅力

自动将基本数据类型转化为对应的封装类型。成为一个对象以后就可以调用对象所声明的所有的方法

自动拆箱:故名思议就是将对象重新转化为基本数据类型:

//装箱

Integer num = 10;

//拆箱

int num1 = num;自动拆箱有个很典型的用法就是在进行运算的时候:因为对象时不恩直接进行运算的,而是要转化为基本数据类型后才能进行加减乘除

Integer num = 10;

//进行计算时隐含的有自动拆箱

System.out.print(num--);哈哈 应该感觉很简单吧,下面我再来讲点稍微难点的,

//在-128~127 之外的数

Integer num1 = 297; Integer num2 = 297;

System.out.println("num1==num2:"+(num1==num2));

// 在-128~127 之内的数

Integer num3 = 97; Integer num4 = 97;

System.out.println("num3==num4:"+(num3==num4)); 打印的结果是:num1==num2: false num3==num4: true

 

很奇怪吧:这就归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:叫享元模式(flyweight)

为了加大对简单数字的重利用,java定义:在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象

而如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象;明白了吧 

以上的现象是由于使用了自动装箱所引起的,如果你没有使用自动装箱,而是跟一般类一样,用new来进行实例化,就会每次new就都一个新的对象;

这个的自动装箱拆箱不仅在基本数据类型中有应用,在String类中也有应用,比如我们经常声明一个String对象时:

复制代码代码如下:

 

String str = "sl";

//代替下面的声明方式

String str = new String("sl");

 

基本数据(Primitive)类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。虽然为您打包基本数据类型提供了方便,但提供方便的同时表示隐藏了细节,建议在能够区分基本数据类型与对象的差别时再使用。

autoboxing和unboxing

在Java中,所有要处理的东西几乎都是对象 (Object),例如之前所使用的Scanner是对象,字符串(String)也是对象,之后还会看到更多的对象。然而基本(Primitive)数据类型不是对象,也就是您使用int、double、boolean等定义的变量,以及您在中直接写下的字面常量。

在前一个小节中已经大致看到了操作对象的方便性,而使用Java有一段时间的人都知道,有时需要将基本数据类型转换为对象。例如使用Map对象要put()方法时,需要传入的参数是对象而不是基本数据类型。

要使用打包类型(Wrapper Types)才能将基本数据类型包装为对象,前一个小节中您已经知道在J2SE 5.0之前,要使用以下语句才能将int包装为一个Integer对象:Integer integer = new Integer(10);

在 J2SE 5.0之后提供了自动装箱的功能,您可以直接使用以下语句来打包基本数据类型:Integer integer = 10;

在进行编译时,编译器再自动根据您写下的语句,判断是否进行自动装箱动作。在上例中integer参考的会是Integer类的实例。同样的动作可以适用于 boolean、byte、short、char、long、float、double等基本数据类型,分别会使用对应的打包类型(Wrapper Types)Boolean、Byte、Short、Character、Long、Float或Double。下面直接使用自动装箱功能来改写范例 4.4。

 

范例4.5 AutoBoxDemo.java

复制代码代码如下:

 

public class AutoBoxDemo {

public static void main(String[] args) {

Integer data1 = 10;

Integer data2 = 20;

// 转为double值再除以3

System.out.println(data1.doubleValue() /3);

// 进行两个值的比较

System.out.println(data1.compareTo(data2));

}

}

 

程序看来简洁了许多,data1与data2在运行时就是Integer的实例,可以直接进行对象操作。的结果如下:

3.3333333333333335

–1

自动装箱运用的方法还可以如下:

复制代码代码如下:

 

int i = 10;

Integer integer = i;

 

也可以使用更一般化的java.lang.Number类来自动装箱。例如:

Number number = 3.14f;

3.14f会先被自动装箱为Float,然后指定给number。

从J2SE 5.0开始可以自动装箱,也可以自动拆箱(unboxing),也就是将对象中的基本数据形态信息从对象中自动取出。例如下面这样写是可以的:

复制代码代码如下:

 

Integer fooInteger = 10;

int fooPrimitive = fooInteger;

 

fooInteger引用至自动装箱为Integer的实例后,如果被指定给一个int类型的变量fooPrimitive,则会自动变为int类型再指定给fooPrimitive。在运算时,也可以进行自动装箱与拆箱。例如:

复制代码代码如下:

 

Integer i = 10;

System.out.println(i + 10);

System.out.println(i++);

 

上例中会显示20与10,编译器会自动进行自动装箱与拆箱,也就是10会先被装箱,然后在i + 10时会先拆箱,进行加法运算;i++该行也是先拆箱再进行递增运算。再来看一个例子:

复制代码代码如下:

 

Boolean boo = true;

System.out.println(boo && false);

 

同样的boo原来是Boolean的实例,在进行AND运算时,会先将boo拆箱,再与false进行AND运算,结果会显示false。

//

装箱:从基本类型转换成Object类型,称之为装箱;***拆箱:从Object转换乘基本类型的操作,称之为拆箱。这个操作在反射过程中用的比较的多。

装箱:在堆中建立一个Object实例,把你指定的值复制成去;***拆箱:判别引用指向的堆中信息是否是要拆成的类型,是取出堆中值送给栈中变量,否则报异常

///

装箱是值类型到object类型或到该值类型所实现的任何接口类型的隐士转换。

将一个值类型装箱会分配一个对象实例并将该值复制到新的对象中。

复制代码代码如下:

 

int i=123;

object o=i;

 

这句话的结果是在堆栈上创建一个对象o,而该对象在堆上引用int类型的值。该值是赋值给变量i

的值类型值的一个副本。

下面是显示执行装箱转换

复制代码代码如下:

 

int i=123;

ojbect o=(object)i;

 

此例将整数变量i通过装箱转换为对象o。这样,存储在变量i中的值就从123改为456。此例显示对象保留了内容的原始副本。即123。

取消装箱是从object类型到值类型或从接口类型到实现该接口的值类型的显示转换。取消装箱操作包括:

检查对象实例,确保它是给定值类型的一个装箱值。

将该值从实例复制到值类型变量中。

例子:

复制代码代码如下:

 

int i=123;

object box=i;

int j=(int)box;

9.接口和抽象类的区别是什么?

程序设计所面对的问题域——客观世界,是由许多事物构成的,这些事物既可以是有形的(比如一辆汽车),也可以是无形的(比如一次会议)。把客观世界中的事物映射到面向对象的程序设计中就是对象。对象是面向对象程序设计中用来描述客观事物的程序单位。客观世界中的许多对象,无论其属性还是其行为常常有许多共同性,抽象出这些对象的共同性便可以构成类。所以,类是对象的抽象和归纳,对象是类的实例。

 

抽象方法:仅有定义,没有具体实现的方法

抽象类:含有抽象方法的类

一个类如果被定义为抽象类,它就不能被实例化,也就是说,不能有自己的对象

 

声明接口使用关键字“interface”

接口中一般只包含一组public抽象方法(且必须是公有抽象方法,但方法定义中public abstract可省略),也可以包含public 静态final数据

Java不允许一个子类继承多个超类,却允许一个子类继承一个超类并实现多个接口.

 

给你举个例子吧。比如一个公司,有老板,老板聘的经理,还有员工,

 

类就是员工,抽象类就是经理,接口就是老板。

 

接口里就是给个方法,但是他自己不做,比如老板说我要那个文件,给我定个机票,我要那个策划方案等,都是下面人做。老板只说不做。

 

抽象类给的方法,有的他自己做,有的其他人做。比如经理说我要那个文档,员工就要发给他,但是他自己也要做点事,比如拿方案给老板看。经理又说又做。

 

一般类给的方法,就是什么都要做,都要实现。属于不说必须做的。

34.接口是否可继承接口?接口类是否实现接口?接口类是否可继承实体类?

接口是可以继承接口的

 

面试常考题

Java抽象类可以有构造函数吗?

抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。

在继承了抽象类的子类中通过super(参数列表)调用抽象类中的构造方法

Java抽象类可以实现接口吗?它们需要实现所有的方法吗?

可以

不需要,抽象类可以不实现接口的方法,由抽象类的子类实现。

Java抽象类可以是final的吗?

Java抽象类不可以被 final修饰

抽象类需要被继承才能使用,而被final修饰的类无法被继承,所以abstract和final是           不能共存的。

Java抽象类可以有static方法吗?

Java抽象类中不能有静态的抽象方法。

 

原因:抽象类是不能实例化的,即不能被分配内存;而static修饰的方法在类实例化之前就已经别分配了内存,这样一来矛盾就出现了:抽象类不能被分配内存,而static方法必须被分配内存。所以抽象类中不能有静态的抽象方法。

 

另外,定义抽象方法的目的是重写此方法,但如果定义成静态方法就不能被重写。

可以创建抽象类的实例吗?

不可以

抽象类必须有抽象方法吗?

抽象类可以没有抽象方法,但是如果你的一个类已经声明成了抽象类,即使这个类中没有抽象方法,它也不能再实例化,即不能直接构造一个该类的对象。

如果一个类中有了一个抽象方法,那么这个类必须声明为抽象类,否则编译通不过。

Java抽象类和接口有何不同?

1、抽象类是类,它的子类不能再继承其它类了,但可以实现一个和多个接口。接口不是类,它的子接口可以继承多个接口。

2、抽象类中是可以有不用abstract修饰的方法,而接口中只能有抽象方法,即方法都要用abstract修饰。抽象类中除了能定义抽象方法以外,也可以定义具体的方法,并且可以定义方法体内容.接口中是不可以定义具体的方法实现,他只能允许你定义方法但是不能有任何方法体.

3、抽象类可以实现接口,而接口是不能继承或实现抽象类的。

何时选用抽象类而不是接口?

接口是一种协定,抽象类则相当于类模板。

使用抽象类,而不要使用接口来分离协定与实现。

如果需要提供多态层次结构的值类型,使用接口。

如果一个类型必须实现多个协定,或者协定适用于多种类型,使用接口。

虽然抽象类和接口都支持将协定与实现分离开来,但接口不能指定以后版本中的新成员,而抽象类可以根据需要添加成员以支持更多功能。

优先考虑定义类,而不是接口。

 

1.写一个形状接口Shape  有两个方法一个求周长,一个求面积    2. 写一个长方形类Rect继承于形状类  增加属性长和宽  分别去覆盖求周长和求面积的方法    3.写一个圆形类Circle  增加属性半径  分别去覆盖求周长和求面积的方法  写一个测试类,在测试类中分别创建不同的对象放入进一个Shape  数组中进行,循环数组中的元素求周长和面积

package com.jiale.demo01;

 

public interface Shape {

    void Perimeter();

    void Area();

}

 

package com.jiale.demo01;

 

public class Rect implements Shape {

   

    public Rect(int length, int wide) {

       // TODO自动生成的构造函数存根

       setLength(length);

       setWide(wide);

    }

   

    private int length;

    private int wide;

 

    public int getLength() {

       return length;

    }

 

    public void setLength(int length) {

       this.length = length;

    }

 

    public int getWide() {

       return wide;

    }

 

    public void setWide(int wide) {

       this.wide = wide;

    }

 

    @Override

    public void Perimeter() {

       // TODO自动生成的方法存根

       System.out.println("长方形长为:"+this.length+宽为: "+this.wide+" 它的周长是:"+((this.length*2)+(this.wide*2)));

    }

 

    @Override

    public void Area() {

       // TODO自动生成的方法存根

       System.out.println("长方形长为:"+this.length+宽为: "+this.wide+" 它的面积是:"+(this.length*this.wide));

    }

 

}

 

package com.jiale.demo01;

 

public class Circle implements Shape {

   

    public Circle(double radius) {

       // TODO自动生成的构造函数存根

       setRadius(radius);

    }

   

    private double radius;

 

    public double getRadius() {

       return radius;

    }

 

    public void setRadius(double radius) {

       this.radius = radius;

    }

 

    @Override

    public void Perimeter() {

       // TODO自动生成的方法存根

       System.out.println("圆的半径为:"+this.radius+" 它的周长是:"+(2*3.14*this.radius));

    }

 

    @Override

    public void Area() {

       // TODO自动生成的方法存根

       System.out.println("圆的半径为:"+this.radius+" 它的面积是:"+(3.14*this.radius*this.radius));

    }

 

}

 

package com.jiale.demo01;

 

public class demo01 {

 

    public static void main(String[] args) {

       // TODO自动生成的方法存根

       Shape[] shape = new Shape[2];

       Rect a = new Rect(2,3);

       Circle b = new Circle(3);  

       shape[0] = a;  

       shape[1] = b;  

       for(int i=0;i<2;i++){   

           shape[i].Perimeter();  

           shape[i].Area();        

       }  

    }

 

}

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值