现在的位置: 首页 > 综合 > 正文

java程序设计–孙鑫java无难事Lesson5《java常用包、数据类型与引用类型、函数参数传递、克隆机制》

2013年08月14日 ⁄ 综合 ⁄ 共 5289字 ⁄ 字号 评论关闭
java程序设计--孙鑫java无难事Lesson5《java常用包、数据类型与引用类型、函数参数传递、克隆机制》

本节要点:

1.Java的常用包

2.“==”和“equals”的用法

3.基本数据类型与引用类型

4.String和StringBuffer

5.对象的克隆(clone)

详细内容:
1.Java的常用包
java.applet:包含一些用于创建Java小应用程序的类。
java.awt:包含一些用于编写与平台无关的图形界面(GUI)应用程序的类。
java.io:包含一些用作输入输出(I/O)处理的类。
java.lang:包含一些Java语言的基本类与核心类,如String、Math、Integer、System和Runtime,提供常用的功能,这个包中的所有类是被隐式导入的。

java.net:包含用于建立网络连接的类,与java.io同时使用完成与网络有关的读写。

java.util:包含一些实用工具类和数据结构类。

2.“==”和“equals”的用法--变量与对象值相等的判定方法
(1)引用类型
在Java中,boolean、byte、short、int、long、char、float、double这八种是基本数据类型,其余的都是引用类型。
(2)变量与对象值相等的判定
“==”是比较两个变量的值是否相等,“equals”是比较两个对象变量所代表的对象的内容是否相等。
测试代码:
//变量和对象值相等的判定
String str1=new String("abc");
String str2=new String("abc");
String str3=new String("abc");
if(str1==str2)
  System.out.println("str1==str2");
else
      System.out.println("str1!=str2");//str1!=str2  ==比较两个变量的值
 if(str1==str3)
       System.out.println("str1==str3");
   else
       System.out.println("str1!=str3");//str1!=str3  ==比较两个变量的值
    if(str1.equals(str2))
        System.out.println("str1==str2");//str1==str2  equals比较两个变量所引用的对象是否相等
     else
           System.out.println("str1!=str2");
3.基本数据类型与引用类型--内存模型简析

(1)基本数据类型的内存分配

内存分配过程:

a.声明引用变量,分配栈内存,引用变量值为null
b.new操作符在堆内存中分配空间返回堆内存地址

c.将堆内存地址赋给引用变量

基本数据类型内存分配如下图:

语句num=null;切断与原数组关联如下图:


(2)对象的内存分配

分配过程见下图:


(3)函数调用时的内存模型

在Java中,传参时,都是以传值的方式进行。
对于基本数据类型,传递的是数据的拷贝;对于引用类型,传递的引用的拷贝。

a.基本数据类型数据交换

基本数据类型的数据交换并不会实际交换两个数据,因为参数传递时,将会在函数中拷贝一分原数据的副本,而不是操作原数据。

//测试代码及内存模型如下图所示:


b.引用类型的数据交换

引用类型的数据交换将真正实现两个数据的交换,因为实际上是对同一对象的操作。

//测试代码及内存模型如下图所示:


4.String和StringBuffer的特性和使用
(1)String的"+"和"+=",是java中唯一被重载的操作符;在java中不允许程序员重载操作符。
字符串可以和任意类型变量相加.
(2)String是一个常量,可以理解为将一个堆中对象的地址赋给这个String对象来引用,因此String类的值将保留对象的地址引用而不能改变。为什么使用这种机制?
这种机制能够避免像语句:
String str1=new String("abc");//分配堆内存并将地址赋给引用变量str1
str1="bcd";//重新分配堆内存
这样将会造成内存浪费,因此java避免更改String中的内容,要更改其内容,可以换用StringBuffer类。在大量处理字符串的程序中使用StringBuffer类。
(3)插入、删除等其他操作  可以参见api帮助文档
//String类测试代码
//字符串使用
String str1=new String("abc");
int i=3;
float f=1.5f;
char ch='f';
boolean b=false;
//System.out.println(str1+i+f+ch+b);//ok  String类允许任意类型相加  abc31.5ffalse
StringBuffer  sb=new StringBuffer();
sb.append(str1).append(i).append(f).append(ch).append(b);
//System.out.println(sb.toString());//ok
sb.delete(4,8);//4-7error  计算索引时 包含前一个索引 但不包含后一个(结束索引)索引
sb.insert(4,"InsertTest");//插入字符串
 System.out.println(sb);//ok  自动调用toString
5.克隆(clone)机制--解决引用类型的数据保护
(1)克隆机制作用
在函数中传递参数时,传递引用类型的参数时可能导致原数据的更改,为了避免原数据的更改,采用克隆(clone)机制。克隆机制拷贝原对象的一份数据,而不对原数据直接进行操作。
(2)实现克隆机制
克隆机制的实现需要在派生类中实现Cloneable接口、覆盖基类的clone()方法,并声明为public并且派生类的clone()方法中调用super.clone()。
为什么要调用super.clone()?
在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
//测试代码
class Student  implements Cloneable
{
    int age;
    String name;
    Student(String name,int age )
    {
        this.name=name;
        this.age=age;
    }
    //浅层次的拷贝
    public Object clone()
    {   
        Object o =null;
        try
        {
            o=super.clone();
        }
        catch (CloneNotSupportedException e)
        {
            System.out.println(e.toString());
        }
        return  o;
    }
}
//main函数中
//对象克隆  
Student stu1=new Student("zhangsan",18);
Student stu2=(Student)stu1.clone();//克隆后不影响原对象的数据
stu2.name="LiSi";
stu2.age=20;//不会修改stu1的数据
System.out.println("stu1.name="+stu1.name+" stu1.age="+stu1.age);
//运行结果
stu1.name=zhangsan stu1.age=18
(3)克隆机制引发的问题---深层次克隆
//测试代码
class professor
{
    int age;
    String name;
    professor(String name,int age)
    {
        this.name=name;
        this.age=age;
    }
}
class Student  implements Cloneable
{
    int age;
    String name;
    professor p;//引用类型
    Student(String name,int age,professor p)
    {
            this.name=name;
        this.age=age;
        this.p=p;
    }
    //浅层次的拷贝
    public Object clone()
    {   
        Object o =null;
        try
        {
            o=super.clone();
        }
        catch (CloneNotSupportedException e)
        {
            System.out.println(e.toString());
        }
        return  o;
    }
}
//main函数中
professor p=new professor("WangWu",50);
Student stu1=new Student("zhangsan",18,p);
Student stu2=(Student)stu1.clone();
stu2.p.name="Zhaoer";
stu2.p.age=44;//会修改stu1.p的数据  
System.out.println("stu1.p.name="+stu1.p.name+" stu1.p.age="+stu1.p.age);
//运行结果
stu1.p.name=Zhaoer stu1.p.age=44
说明克隆的时候仍然修改了原对象stu1的数据,解决方法:让professor实现Cloneable接口和clone方法
//更改后的测试代码
class professor implements Cloneable
{
    int age;
    String name;
    professor(String name,int age)
    {
        this.name=name;
        this.age=age;
    }
    //支持克隆
    public Object clone()
    {   
        Object o =null;
        try
        {
            o=super.clone();//必须调用 复制的不是基类对象而是运行时识别复制的对象
        }
        catch (CloneNotSupportedException e)
        {
            System.out.println(e.toString());
        }
        return  o;
    }
    
}
class Student  implements Cloneable
{
    int age;
    String name;
    professor p;//引用类型
    Student(String name,int age,professor p)
    {
        this.name=name;
        this.age=age;
        this.p=p;
    }
    //深层次的拷贝
    public Object clone()
    {   
        Student s =null;
        try
        {
            s=(Student)super.clone();
        }
        catch (CloneNotSupportedException e)
        {
            System.out.println(e.toString());
        }
        s.p=(professor)s.p.clone();//复制引用类型的成员变量
        return  s;
    }
    
}
//main函数中
professor p=new professor("WangWu",50);
Student stu1=new Student("zhangsan",18,p);
Student stu2=(Student)stu1.clone();
stu2.p.name="Zhaoer";
stu2.p.age=44;//不会修改stu1.p的数据  
System.out.println("stu1.p.name="+stu1.p.name+" stu1.p.age="+stu1.p.age);
//运行结果
stu1.p.name=WangWu stu1.p.age=50
这说明没有修改stu1的数据。
6.main函数中的命令行参数
//获取命令行参数
for(int i=0;i<args.length;i++)
   System.out.println(args[i]);

抱歉!评论已关闭.