面向对象的基础篇_02

来源:互联网 发布:php编写新闻发布系统 编辑:程序博客网 时间:2024/06/03 20:18

基础篇_02的主要内容

  • 1、引用传递和值传递
  • 2、链表

一丶引用传递和值传递

1、基本类型和引用类型在内存中的保存

|- Java中数据类型分为两大类,【基本类型】和【对象类型】。

  • 基本类型的变量保存原始值,即它代表的值就是数值本身;
    • 这里的基本类型包括:byte,short,int,long,char,float,double,Boolean,returnAddress,etc...
  • 引用类型的变量保存引用值。
    • "引用值"指向内存空间的地址,代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置。
    • 引用类型包括:类类型,接口类型和数组。

2、变量的基本类型和引用类型的区别

|- 变量也有两种类型:【基本类型】和【引用类型】。

  • 基本数据类型在声明时系统就给它分配空间:

    int a;
    a=10;//正确,因为声明a时就分配了空间
  • 引用就不相同了,它声明时只给变量分配了引用空间,而不分配数据空间:
Date date;date=new Date();date.getDate();//执行实例化,开辟数据空间存放Date对象,然后把空间的首地址传给“今天到的日期”变量  System.out.println(date.getDate());//输出今天的日期/* *如果注释掉date=new Date();就会有异常抛出 *NullPointerException,意思就是说一个空的变量,一个空的栈内存。 *The local variable date may not have been initialized *也就是说对象的数据空间没有分配 */

3、引用传递和值传递

引用传递是Java的核心问题,引用传递的操作的核心就是内存地址的传递。
这里要用 【实际参数】 和 【形式参数】的概念来帮助理解,

  • 值传递:
    方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值。

      • 范例:
              public class Test01 {                    public static void change(int a){                        a=10000;                    }                    public static void main(String[] args) {                    int a=10;                    System.out.println(a);//10                    change(a);                    System.out.println(a);//10                    }                }

椭圆是中a是实际参数,拷贝的a是形式参数
改变的是形式参数的值,结果不影响实际参数。

  • 引用传递:也称为传地址。
    方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址;在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。

      • 范例:
                public class Test02 {                    public static void change(int []a){                        a[0]=50;                    }                    public static void main(String[] args) {                        int []a={10,20};                        System.out.println(a[0]);//10                        change(a);                        System.out.println(a[0]);//50                    }                }

椭圆是中a是实际参数,拷贝的a是形式参数
这里传来的是地址,形式参数和实际参数有一样的地址,改变了地址中的内容

  • 通过以下三个Demo来说明作用
class Demo{    private int count = 10 ;    public void setCount(int count){    this.count = count ;    }    public int getCount(){    return this.count ;    }};public class Demo01 {    public static void main(String args[]){        Demo d1 = new Demo() ;        d1.setCount(100) ;        fun(d1) ;        System.out.println(d1.getCount()) ;        //输出的结果为30    }    public static void fun(Demo d2){        d2.setCount(30) ;    }};
public class Demo02 {    public static void main(String args[]){        String str = "hello" ;            fun(str) ;        System.out.println(str) ;        //输出的结果是hello    }    public static void fun(String temp){        temp = "world" ;    }};
  • 字符串的内容无法改变,改变的只是内存地址的指向。
class Demo{    private String str = "hello" ;    public void setStr(String str){        this.str = str ;        }    public String getStr(){        return this.str ;    }};public class Demo03 {    public static void main(String args[]){        Demo d1 = new Demo() ;        d1.setStr("world") ;        fun(d1) ;        System.out.println(d1.getStr()) ;        //最后的输出结果是!!!    }    public static void fun(Demo d2){        d2.setStr("!!!") ;    }};

二丶链表的认识(这里是说一个指针域的)

1、链表是一个个结点连接起来的长链。

  • 链表包括两个部分
    • |-数据域:存放数据的区域。例如:姓名、地址、学号etc...
    • |-指针域:存放一个指针的区域。这个指针
class Node {    private String name ; // 保留节点名称    private Node next ;   // 保存下一个节点的引用    public Node(String name){  //含有参数的构造器来保存结点名称        this.name = name ;        //this.name中的name是Node类中的name        //= name 是传过来参数name    }    public String getName(){        return this.name ;    }    public void setNext(Node next){        this.next = next ;    }    public Node getNext(){        return this.next ;    }}public class Demo04 {    public static void main(String args[]){        Node na = new Node("A") ;        Node nb = new Node("B") ;        Node nc = new Node("C") ;            na.setNext(nb) ;//a的指针域指向b            nb.setNext(nc) ;//b的指针域指向c    }}

在栈内存中存放的是na,nb,nc
在堆内存中存放的是name:A、B、C 和next:nb、nc、null

  • 第一个结点A的指针域na指向的是nb,所以堆内存中存放的是结点A到的name和nb。同理可得。
    在设置好了关系之后,只能通过递归的方式完成全部输出。
public class Demo05 {    public static void main(String args[]){        Node na = new Node("车厢 A") ;        Node nb = new Node("车厢 B") ;        Node nc = new Node("车厢 C") ;            na.setNext(nb) ;            nb.setNext(nc) ;            print(na) ;    }    public static void print(Node node){        if(node != null){ // 避免空指向异常            System.out.println(node.getName()) ;            if(node.getNext() != null){                print(node.getNext()) ;            }        }    }}

自动的完成增加和输出的功能

  • 需要考虑到以下的几个问题:
    • 每一个结点都要保存起来。设置一个可以保存节点关系的类:Node
    • 需要一个添加结点,并按照结点次序连接起来的类:Link
    • 第一个结点是头结点,必须保留好根节点,private封装起来

下面是一个链表的基本数据模型。

class Node {    private String name ; // 保留节点名称    private Node next ;  // 保存下一个节点的引用    public Node(String name){        this.name = name ;    }    public String getName(){        return this.name ;    }    public void setNext(Node next){        this.next = next ;    }    public Node getNext(){        return this.next ;    }    public void addNode(Node newNode){//添加结点        if(this.next == null){            this.next = newNode ;        } else {            this.next.addNode(newNode) ;  // 当前节点的下一个继续往下判断        }    }    public void printNode(){//输出结点        System.out.println(this.name) ;        if(this.next != null){            this.next.printNode() ;        }    }}class Link {  // 表示的是一个节点的操作类    private Node root ;  // 表示根节点    public void add(String name){  // 增加新节点        Node newNode = new Node(name) ;  // 新节点        if(this.root == null){  // 现在没有根节点            this.root = newNode ; // 第一个节点是根节点        } else {  // 应该排在最后            this.root.addNode(newNode) ;  // 向后面排队        }    }    public void print(){        this.root.printNode() ;//从根结点开始调用,这个函数的方法在类Node中    }}public class Test {    public static void main(String args[]){        Link link = new Link() ;        link.add("车厢 A") ;        link.add("车厢 B") ;        link.add("车厢 C") ;        link.add("车厢 D") ;        link.add("车厢 E") ;        link.print() ;    }}