面向对象的基础篇_02

基础篇_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() ;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值