ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第四章 面向对象(一)

2022-06-25 18:33:27  阅读:117  来源: 互联网

标签:String int void class 面向对象 new public 第四章


第四章 面向对象(一)

学习面向对象的三条主线:

  • Java类及类的成员:属性,方法,构造器,代码块,内部类
  • 面向对象的三大特征:封装性,继承性,多态性,(抽象性)
  • 其它关键字:this,super,final

4.1面向过程与面向对象

面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做。

面向对象:将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。

4.2Java基本元素:类和对象

类:对一类事物的描述,是抽象的、概念上的定义

对象:实际存在的该类事物的每个个体,因而也称为实例(instance)

对象是有类派生出来的

理解”万事万物皆对象“

1.在Java语言范畴中,我们都将功能,结构等封装到类中,通过类的实例化,来调用具体的功能结构。如:Scanner,String等

文件:file,忘了资源:URL;

2.涉及到Java语言与前端Html,后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类,对象。

类的成员:属性和方法

属性=成员变量=field(域,字段)

方法=成员方法=函数=method

创建类的对象=类的实例化=实例化类

4.3对象的创建和使用

类的访问机制

1.在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。(例外:static方法访问非static,编译不通过)

2.在不同类中的访问机制:先创建要访问的对象,再用对象访问类中定义的成员

public class classTest1{
  public static void main(String[] args){
    Person p1=new Person();
    p1.name="Tom";
    p1.isMale=true;
    p1.eat();
    p1.sleep();
    Person p3=p1;//将p1地址值赋给p3
    System.out.println(p3.name);//Tom
    p3.age=10;
    System.out.println(p1.name);//10 p3,p1指向同一个对象
  }
}
class Person{
  String name;
  boolean isMale;
  int age=1;
  public void eat(){
    System.out.println(name+"吃饭");
  }
  public void sleep(){
    System.out.println(name+"睡觉");
    eat();//类中访问机制
  }
}

对象的生命周期


内存解析

运行时候分配空间

JVM内存结构:编译完程序以后,生成一个或多个字节码文件。我们是用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行。

意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。

堆(Heap),此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。

通常所说的栈(Stack),是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完,自动释放。

方法区(Method Area),用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

匿名对象

我们也可以不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象。

如:new Person().sleep;

使用情况:

如果对一个对象只需要进行一次方法调用,那么久可以使用匿名对象。我们经常将匿名对象作为实参传递给一个方法调用。

public class classTest1{
  public static void main(String[] args){
    PhoneMall mall=new PhoneMall();
    //Phone p=new Phone();
    //mall.show(p);
    mall.show(new Phone());//将匿名对象传递给方法
  }
}
class PhoneMall{
  public void show(Phone phone){
    phone.sendEmail();
    phone.playGame();
  }
}
class Phone{
  public void sendEmail{}
  public void playGame{}
}

4.4类的成员之一:属性

语法格式:修饰发 数据类型 属性名=初始化值;

属性(成员变量)VS局部变量

成员变量VS局部变量的内存位置:

4.5类的成员之二:方法

方法:描述应该具有的功能

return关键字的使用

使用范围:使用在方法体重

作用:

1.结束方法

2.针对有返回值类型的方法,使用”return 数据“方法返回所要的数据

方法调用的过程分析

练习1

public class classTest1{
  public static void main(String[] args){
    Person p1=new Person();
    p1.name="Tom";
    p1.age=18;
    p1.sex=1;
    p1.study();
    p1.showAge();
    int newAge=p1.addAge(2);//20
    System.out.println(p1.name+"新年龄为:"+newAge);
    System.out.println(p1.age);//20
    Person p2=new Person();
    p2.name="Ali";
    p2.age=23;
    p2.study();
    p2.showAge();
  }
}
class Person{
  String name;
  int age;
  int sex;
  public void study(){
    System.out.println("studying");
  }
  public void showAge(){
    System.out.println(age);
  }
  public int addAge(int i){
    age=age+i;
    return age;
  }
}

内存解析

练习2

利用面向对象的编程方法,涉及类CIrcle计算圆的面积。

//方式一:
public class classTest1{
  public static void main(String[] args){
    Circle c1=new Circle();
    c1.radius=2;
    c1.findArea();
  }
}
class Circle{
  double radius;
  public void findArea(){
    double area=Math.PI*radius*radius;
    System.out.println("圆的面积为"+area);
  }
}
//方式二:
public class calssTest1{
  public static void main(String[] args){
    Circle c1=new Circle();
    c1.radius=2;
    //输出方式1
    //double area=c1.findArea();
    //System.out.println(area);
    //输出方式2
    System.out.println(c1.findArea());//编辑器看到的是返回值
  }
}
class Circle{
  double radius:
  public double findArea(){
    double area=Math.PI*radius*radius;
    return area;
  }
}

练习3

对象数组的题目

public class classTest1{
  public static void main(String[] args){
    Student[] stus=new Student[20];
    for(int i=0;i<stus.length;i++){
      stus[i]=new Student();//对象数组中的每一个都是对象,需要new,类似于二维数组
      stus[i].number=i+1;
      stus[i].state=(int)(Math.random()*(6-1+1)+1);
      stus[i].score=(int)(Math.random()*(100-0+1)+1);
    }
    for(int i=0;i<stus.length;i++){
      System.out.println(stus[i].number+"\t"+stus[i].state+"\t"+stus[i].score);
      }
      System.out.println("***************");
      //输出state=3学生信息
      for(int i=0;i<stus.length;i++){
        if(stus[i].state==3){
          System.out.println(stus[i].number+"\t"+stus[i].state+"\t"+stus[i].score);
          }
        }
          System.out.println("***************");
          //冒泡排序
          for(int i=0;i<stus.length;i++){
            for(int j=0;j<stus.length-i-1;j++){
              if(stus[j].score>stus[j+1].score){
                /*错误:按成绩来排学生的整体排序,不是交互成绩
                int temp=stus[j].score;
                stus[j].score=stus[j+1].score;
                stus[j+1].score=temp;
                */
                Student temp=stus[j];
                stus[j]=stus[j+1];
                stus[j+1]=temp;       
        }
      }
    }
    for(int i=0;i<stus.length;i++){
      System.out.println(stus[i].number+"\t"+stus[i].state+"\t"+stus[i].score);
    }
  }
}
class Student{
  int number;
  int state;
  int score;
}

优化:将遍历和查找,排序封装到方法中

public class classTest1{
  public static void main(String[] args){
    Student[] stus=new Student[20];
    for(int i=0;i<stus.length;i++){
      stus[i]=new Student();
      stus[i].number=i+1;
      stus[i].state=(int)(Math.random()*(6-1+1)+1);
      stus[i].score=(int)(Math.random()*(100-0+1));
    }
    Test test=new Test();
    test.print(stus);
    System.out.println("******************");
    /*方式一查找的使用
    int index=test.getindex(staus,3);
    System.out.println(stus[index].info());
    */
    test.getindex(stus,3);
    System.out.println("********************");
    test.sort(stus);
  }
}
class Student{
  int number;
  int state;
  int score;
  public String info(){
    return number+"\t"+state+"\t"+score;
  }
}
class Test{
  /**
  *@Description输出对象数组
  *@author
  *@date
  *@param arr 对象数组
  */
  public void print(Student[] arr){
    for(int i=0;i<arr.length;i++){
      System.out.println(arr[i].info());
    }
  }
  /**
  *@Description 找到对应年级的学生
  *@auther 
  *@date
  *@param state
  */
  /*
  //方式1 getindex
  public int getindex(Student[] arr,int state){
    int index=-1;
    for(int i=0;i<arr.length;i++){
      if(arr[i].state==state){
        index=i;
      }
    }
    return index;
  }
  */
  //方式2 getindex
  public void getindex(Student[] arr,int state){
    for(int i=0;i<arr.length;i++){
      if(arr[i].state==state){
        System.out.println(arr[i].info());
      }
    }
  }
  /**
  *@Description 冒泡排序
  *@author
  *@date
  *@param arr
  */
  public void sort(Student[] arr){
    for(int i=0;i<arr.length;i++){
      for(int j=0;j<arr.length-i-1;j++){
        if(arr[j].score>arr[j+1].score){
          Student temp=arr[j];
          arr[j]=arr[j+1];
          arr[j+1]=temp;
        }
      }
    }
    print(arr);
  }
}

内存解析

引用类型的变量,只可能存储两类值:null或地址值(含变量类型)

方法重载

1.定义:在同一个类中,允许一个以上的同名方法,只要它们的参数个数或者参数类型

不同即可

2.例如:Arrays类中重载的sort(),binarySearch()

3.判断是否是重载:跟方法的权限修饰符,返回值类型,形参变量名,方法体都没有关系。

4.在通过对象调用方法时,如何确定某一个指定的方法:方法名-参数列表

//以下构成方法重载
public void getsum(String s,int i){}
public void getsum(int i,String s){}

练习1

可变个数的形参

Jdk5.0新增的内容

具体使用:

1.可变个数形参的格式:数据类型...变量名

2.当调用可变个数形参的方法时,传入的参数个数可以是:0,1,2...

3.可变个数形参的方法与本类中方法名相同,形参不同的方法构成重载

4.可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载,两者不能同时存在。String...strs与String[] strs

5.可变个数形参在方法的形参中,必须声明在末尾

6.可变个数形参在方法的形参中,最多只能声明一个可变形参

应用场景:数据库的多个查找条件

public class classTest2{
  public static void main(String[] args){
    MethodargsTest test=new MethodargsTest();
    test.show("hello");//show(String)
    test.show("hello","world");//show(String ... strs)
    test.show();//show(String ... strs)
    test,show(new String[] {"AA","BB","CC"});//show(String ... strs)
  }
}
class MethodargsTest{
  public void show(String s){
    System.out.println("show(String)");
  }
  public void show(String ... strs){
    System.out.println("show(String ... strs)");
  }
  /*与前面String ... strs等价,jdk5.0之前
  public void show(String[] strs){
  System.out.println("show(String)");
  }
  */
}

方法参数的值传递

变量的赋值:

基本数据类型:赋值的是变量所保存的数据值;

引用数据类型:变量所保存的数据的地址值。

//基本数据类型
//从内存结构来考虑,m和n都在栈内,n改变不影响m
int m=10;
int n=m;
System.out.println("m="+m+",n="+n);//m=10,n=10
n=20;
System.out.println("m="+m+",n="+n);//m=10,n=20

//引用数据类型
//从内存结构来考虑,o1和o2都是同一个地址,指向同一个对象,修改o2会影响o1
public class calssTest2{
  public static void main(String[] args){
    Order o1=new Order();
    o1.orderId=1001;
    Order o2=o1;
    System.out.println("o1.OrderId="+o1.orderId+",o2.OrderId="+o2.orderId);
    //o1.OrderId=1001,o2.OrderId=1001
    o2.orderId=1002;
    System.out.println("o1.OrderId="+o1.orderId+",o2.OrderId="+o2.orderId);
    //o1.OrderId=1002,o2.OrderId=1002
  }
}
class Order{
  int orderId;
}

方法的形参的传递机制:值传递

1.形参:方法定义时,声明的小括号内的参数

实参:方法调用是,实际传递给形参的数据

2.值传递机制:如果参数是基本数据类型,此时实参赋给形参的是,实参真实存储的数据值。如果参数是引用数据类型,此时实参赋给形参的是变量保存的数据的地址值

基本数据类型的参数传递

引用数据类型的参数传递1


引用数据类型的参数传递2

练习1

//基本数据类型的参数传递
public class classTest2{
  public static void main(String[] args){
    ValueTransTest test=new ValueTransTest();
    int m=10;
    int n=20;
    test.swap(m,n);
    System.out.println("m="+m+",n="+n);//m=10,n=20未交换数值
  }
}
class ValueTransTest{
  public void swap(int m,int n){
    int temp=m;
    m=n;
    n=temp;
  }
}

内存解析:

形参m,n在swap结束后被销毁,并不会输出。m和n保持原值。

练习2

//数组的参数传递
public class classTest2{
  public static void main(String[] args){
    ValueTransTest test=new ValueTransTest();
    int[] arr=new int[]{1,2,3,5,7,2,4,0};
    for(int i=0;i<arr.length;i++){
      for(int j=0;j<arr.length-i-1;j++){
        if(arr[j]>arr[j+1]){
          test.swap(arr[j],arr[j+1]);
        }
      }
    }
    for(int i=0;i<arr.length;i++){
      System.out.print(arr[i]+"\t");//1 2 3 5 6 2 4 0
      //未交换,赋给形参的是arr[i],arr[i+1]的真实数据
    }
  }
}
class ValueTransTest{
  public void swap(int m,int n){
    int temp=m;
    m=n;
    n=temp;
  }
}

//引用数据类型的传递
public class classTest2{
  public static void main(String[] args){
    ValueTransTest test=new ValueTransTest();
    Data data=new Data();
    data.m=10;
    data.n=20;
    /*
    int temp=data.m;
    data.m=data.n;
    data.n=temp;
    System.out.println("m="+data.m+",n="+data.n);//m=20,n=10
    */
    test.swap(data);
    System.out.println("m="+data.m+",n="+data.n);//m=20,n=10
  }
}
class ValueTransTest{
  public void swap(Data data){
    int temp=dara.m;
    data.m=data.n;
    data.n=temp;
  }
}

内存解析:

swap结束后,局部变量temp和形参data被销毁,但是m和n已经改变。

正确交换数组值的方法

public class classTest2{
  public static void main(String[] args){
    ValueTransTest test=new ValueTransTest();
    int[] arr=new int[]{1,2,3,5,7,2,4,0};
    for(int i=0;i<arr.length;i++){
      for(int j=0;j<arr.length-i-1;j++){
        if(arr[j]>arr[j+1]){
          test.swap(arr,j,j+1);
        }
      }
    }
    for(int i=0;i<arr.length;i++){
      System.out.print(arr[i]+"\t");//0 1 2 2 3 4 5 7
      //交换,赋给形参的是arr的地址值
    }
  }
}
class ValueTransTest{
  public void swap(int[] arr,int i,int j){
    int temp=arr[i];
    arr[i]=arr[j];
    arr[j]=temp;
  }
}

练习3

以下程序的输出值

public class classTest2{
  public static void main(String[] args){
    classTest2 test=new classTest2();
    //在一个类中的访问机制:类中的方法可以直接访问类中的成员变量
    //但是static访问非static要先new一个对象
    test.first();
  }
  public void first(){
    int i=5;
    Value v=new Value();
    v.i=25;
    second(v,i);
    System.out.println(v.i);//20
  }
  public void second(Value v,int i){
    i=0;
    v.i=20;
    Value val=new Value();
    v=val;
    System.out.println(v.i+" "+i);//15 0
  }
}
calss Value{
  int i=15;
}

内存解析:

先退出second方法,second中val,i,v被释放,堆空间中的对象没有指针也被释放。然后退出first方法,second中i,v被释放,堆空间中的对象没有指针也被释放。最后释放test指向的对象,结束程序。

补充:String的值传递

public class calssTest2{
  public static void main(String[] args){
    classTest2 test=new classTest2();
    String s1="hello";
    test.change(s1);
    System.out.println(s1);//hello
  }
  public void change(String s){
    s="hi~~";
  }
}

内存解析:

String是存储在方法区内,并且不可变序列。

扩展练习1

扩展练习2

int[] arr=new int[]{1,2,3};
System.out.println(arr);//地址值?  [I@15db9742
char[] arr1=new char[]{'q','a','b','c'};
System.out.println(arr1);//地址值?  qabc
//这是因为println(char)的功能就是遍历

练习4

public class classTest2{
  public static void main(String[] args){
    PassObject p1=new PassObject();
    //p1.printAreas(new Circle(),5);
    Circle c=new Circle();
    //System.out.println(c.redius);//0
    p1.printAreas(c,5);
    //System.out.println(c.radius);//5
  }
}
class Circle{
  double radius;
  public double findArea(){
    return Math.PI*radius*radius;
  }
}
class PassObject{
  public void printAreas(Circle c,int time){
    System.pit.println("Radius\t\tArea");
    for(int i=1;i<=time;i++){
      c.radius=i;
      System.out.println(c.radius+"\t"+c.findArea());
    }
  }
}
/*
 * 
Radius		Area
1.0	3.141592653589793
2.0	12.566370614359172
3.0	28.274333882308138
4.0	50.26548245743669
5.0	78.53981633974483
 */

递归方法

递归方法:一个方法体内调用它自身。

方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无序循环控制。递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。

练习1:

n的阶乘

public class classTest2{
  public static void main(String[] args){
    classTest2 test=new classTest2();
    int sum=test.getsum(5);
    System.out.println(sum);
  }
  public int getsum(int n){
    if(n==0){
      return 1;
    }else{return n*getsum(n-1);}
  }
}

练习2

输入一个数据n,计算斐波那契数列(Fibonacci)的第n个值

1 1 2 3 5 8 13 21 34 55

规律:一个数等于前两个数之和

要求:计算斐波那契数列(Fibonacci)的第n个值,并将整个数列打印出来

public class classTest2{
  public static void main(String[] args){
    classTest2 test=new classTest2();
    int sum=test,getsum(6);
    System.out.println(sum);
  }
  public int getsum(int n){
    if(n==1){
      return 1;
    }else if(n==2){return 1;}
    else{
      return getsum(n-1)+getsum(n-2);
    }
  }
}

练习3

汉诺塔问题

练习4

快排

扩展练习

已知有一个数列:当n<=0时,f(n)=1;n>0时,f(n+2)=2*f(n+1),求f(10)的需要调用递归的次数

可以用谦虚遍历的方法来计算

前,中,后序遍历的递归实现

import java.util.Stack;
public calss classTest3{
  public static void main(String[] args){
    TreeNode[] node=new TreeNode[10];//以数组的形式生成一颗完全二叉树
    for(int i=0;i<10;i++){
      node[i]=new TreeNode(i);//赋值
    }
    for(int i=0;i<10;i++){
      if(i*2+1<10)
        node[i].left=node[i*2+1];
      if(i*2+2<10)
        node[i].right=node[i*2+2];
    }
    preOrderRe(node[0]);//0 1 3 7 8 4 9 2 5 6
    System.out.println();
    midOrderRe(node[0]);//7	3	8	1	9	4	0	5	2	6
		System.out.println();
		postOrderRe(node[0]);//7	8	3	9	4	1	5	6	2	0	
  }
  public static void preOrderRe(TreeNode biTree)
	{//递归实现
		System.out.print(biTree.value+"\t");//0	1	3	7	8	4	9	2	5	6
		TreeNode leftTree = biTree.left;
		if(leftTree != null)
		{
			preOrderRe(leftTree);
		}
		TreeNode rightTree = biTree.right;
		if(rightTree != null)
		{
			preOrderRe(rightTree);
		}
	}
	public static void midOrderRe(TreeNode biTree)
	{//中序遍历递归实现
		if(biTree == null)
			return;
		else
		{
			midOrderRe(biTree.left);
			System.out.print(biTree.value+"\t");
			midOrderRe(biTree.right);
		}
	}
	public static void postOrderRe(TreeNode biTree)
	{//后序遍历递归实现
		if(biTree == null)
			return;
		else
		{
			postOrderRe(biTree.left);
			postOrderRe(biTree.right);
			System.out.print(biTree.value+"\t");
		}
	}
  
class TreeNode{//节点结构
	int value;
  TreeNode left;
  TreeNode right;
  
  TreeNode(int value){
    this.value=value;
  }
}

4.6OOP特征一:封装和隐藏

问题的引入:当我们创建一个类的对象后,我们可以通过”对象.属性“的方式,对对象的属性进行赋值。这里赋值操作要有属性数据类型和存储范围的制约。除此之外,没有其他限制条件。但在实际问题中,我们往往需要给属性加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。同时我们需要避免用户再使用”对象.属性“的方式对属性进行赋值,则需要将属性声明为private

public class classTest2{
  public static void main(String[] args){
    Animal a=new Animal();
    a.setLegs(4);
    int legs=a.getLegs();
    System.out.println(legs);//4
    a.setLegs(-1);
    System.out.println(a.getLegs);//0
  }
}
class Animal{
  String name;
  int age;
  private int legs;
  public void seLegs(int l){
    if(l>=0&&l%2==0){
      legs=l;
    }else{legs=0;}
  }
  public int getLegs(){
    return legs;
  }
}

封装性的体现:1.将类的属性XXX私有化,同时,提供公共的方法来获取getXxx和设置setXxx此属性的值

2.不对外保留的私有的方法

3.单例模式(构造器私有化)

4.如果不希望类在包外调用,可以将类设置为缺省的

权限修饰符

练习

public class classTest2{
  public static void main(String[] args){
    Person a=new Person();
    a.setAge(4);
    int age=a.getAge();
    System.out.println(age);//4
    a.setAge(-1);//输入非法数据
  }
}
class Person{
  private int age;
  /*
  public void setAge(int a){
  	if(a>=0&&a<=130){
  		age=a;
  	}else{System.out.println("输入非法数据");}
  }
  */
  public void setAge(int a){
    if(a<0||a>130){
      System.out.println("输入非法数据");
      return;
    }
    age=a;
  }
  public int getAge(){
    return age;
  }
}

4.7类的成员之三:构造器

构造器的作用:创建对象;初始化对象的属性

说明

1.如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器

2.定义构造器的格式:权限修饰符 类名(形参列表){}

3.一个类中定义的多个构造器,彼此构成重载

4.一旦我们显式的定义了类的构造器后,系统就不再提供默认的空参构造器

5.一个类中,至少会有一个构造器

public class classTesr2{
  public static void main(String[] args){
    //创建类的对象:new+构造器
    Person a=new Person();
    Person b=new Person("Tom");
    Person c=new Person("Tom",9);
  }
}
class Person{
  String name;
  int age;
  //构造器
  public Person(){
    System.out.println("Person()...");
    age=4;
  }
  public Person(String n){
    name=n;
  }
  public Person(String n,int a){
    name=n;
    age=a;
  }
}

属性赋值的先后顺序:默认初始化,显式初始化,构造器中的赋值,”对象.方法"或“对象.属性”的方式赋值(前三个只执行一次,最后一个赋值可以额执行多次)

构造器的权限与类的权限一致

JavaBean是一种Java语言写成的可重用组件。JavaBean:公共的类;有一个无参的公共的构造器;有属性,且有对应的get,set方法。

为什么额都要有一个空参的构造器,方便造对象。反射造对象-空参构造器

4.8关键字:this

this关键字的使用:1.this可以用来修饰:属性,方法,构造器2.this修饰属性和方法:this理解为:当前对象在类的方法或构造器中,我们可以使用“this.属性"或"this.方法"的方式,调用当前对象属性或方法。但通常情况下,我们都选择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。

//改善构造器冗余
class Person{
  String name;
  int age;
  //构造器
  public Person(){//无参构造器
    System.out.println("新对象实例化");
  }
  public Person(String name){
    this();//调用本类中的无参构造器
    this.name=name;
  }
  public Person(String name,int age){
    this(name);//调用有一个参数的构造器
    this.age=age;
  }
}

this调用构造器

1.我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器

2.构造器中不能通过"this(形参列表)"方式调用自己

3.如果一个类中有n个构造器,则最多有n-1构造器中使用了"this(形参列表)"

4.规定:"this(形参列表)"必须声明在当前构造器的首行

5.构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器

4.9关键字:package,import

一、package关键字的使用

1.为了更好的实现项目中类的管理,提供包的概念

2.使用package声明类或接口所属的包,声明在源文件的首行

3.包,属于标识符,遵循标识符的命名规则,规范(xxxyyyzzz)

4.每"."一次,就代表一层文件目录

5.同一包下不能命名同名的接口、类;不同的包下,可以命名同名的接口、类

二、import关键字的使用

import:导入

1.在源文件中显式的使用import结构导入指定包下的类、接口

2.声明在包的声明和类的声明之间

3.如果需要导入多个结构,则并列写出即可

4.可以使用"xxx.*"的方式,表示可以导入xxx包下的所有结构

5.如果使用的类或接口是java.lang包下定义的,则可以省略import结构

6.如果使用的类或接口是本包下定义的,则可以省略import结构

7.如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示

8.使用”xxx.*“方式表明可以调用xxx包下的所有结构,但是如果使用的是xxx子包下的结构,则仍需要显示子包的结构

9.import static:导入指定类或接口中的静态结构:属性或方法

import static java.lang.System.*;
import static java.lang.Math.*;
out.println("hello");//out是一个方法
long num=round(123.234);

补充:

public class classTest2{
  public static void main(String[] args){
    Account a=new Account();
    Customer c=new Customer();
    c.account=a;
  }
}
class Account{
  int id;
  double balance;
}
class Customer{
  String firstName;
  String lastName;
  Account account;
}

内存解析:

4.10课后练习

public class classTest2{
  public static void main(String[] args){
    Bank bank=new Bank();
    bank.addCustomer("Jane","Smith");
    System.out.println(bank.getNumberOfCustomers());//1
    bank.getCustomer(0).setAccount(new Account(100));
    bank.getCustomer(0).getAccount().deposit(1000);//成功存入1000.0
    bank.getCustomer(0).getAccount().withdraw(2000);//余额不足
    double balance=bank.getCustomer(0).getAccount().getBalance();
    System.out.println(balance);///1100.00
  }
}
class Account{
  private double balance;
  public Account(double balance){
    this.balance=balance;
  }
  public double getBalance(){
    return balance;
  }
  public void withdraw(double amount){
    if(balance<amount){
      System.out.println("余额不足");
      return;
    }
    balance-=amount;
    System.out.println("成功取出"+amount);
  }
  public void deposit(double amount){
    balance+=amount;
    System.out.println("成功存入"+amount);
  }
}
class Customer{
  private String firstName;
  private String lastName;
  private Account account;
  public Customer(String f,String l){
    this.firstName=f;
    this.lastName=l;
  }
  public Account getAccount(){
    return account;
  }
  public void setAccount(Account account){
    this.account=account;
  }
  public String getFirstName(){
    return firstName;
  }
  public String gerLastName(){
    return lastName;
  }
}
class Bank{
  private Customer[] customers;
  private int numberOfCustomers;
  public Bank(){
    customers=new Customer[10];//初始化数组
  }
  public void addCustomer(String f,String l){
    Customer cust=new Customer(f,l);
    customers[numberOfCustomers]=cust;
    numberOfCustomers++;
  }
  public int gerNumberOfCustomers(){
    return numberOfCustomers;
  }
  public Customer getCustomer(int index){
    if(index>=0&&index<numberOfCustomers){
      return customers[index];
    }else{return null;}
  }
}

内存解析:

转载:https://blog.csdn.net/alyja/article/details/107017910

标签:String,int,void,class,面向对象,new,public,第四章
来源: https://www.cnblogs.com/caoj/p/16412153.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有