🔭学习内容
掌握对象数组的概念及用法。
掌握内部类的特点及应用,以及内部类调用方法中参数的要求。
对学习内容进行实例分析。
✈️目录
🔭1、对象数组
🔭2、内部类
(1)基本定义
(2)使用static定义内部类
(3)在外部访问内部类
(4)在方法中定义内部类
🔭3、实例讲解
(1)系统登录
(2)单向链表实现(一)
(3)单向链表实现(二)
🔭1、对象数组
所谓的对象数组,就是指包含了一组相关的对象的数组
说明:数组一定要先开辟空间,但是因为其是引用数据类型,所以数组中的每一个对象都是null值,则在使用时数组中的每一个对象必须分别进行实例化操作。
🌳对象数组的声明:
类[ ] 对象数组名称=new 类[数组长度] ;
🌳范例:
class Person{ private String name; public Person(String name){ this.name=name; } public String getName() { return this.name; } } public class Demo{ public static void main(String[] args) { Person[] per=new Person[3];//声明一个对象数组,元素为默认值 System.out.print("数组声明:"); for(int i=0;i<per.length;i++){ System.out.print(per[i]+"、"); } per[0]=new Person("张三"); per[1]=new Person("李四"); per[2]=new Person("王五"); System.out.print("\n对象实例化:"); for(int i=0;i<per.length;i++){ System.out.print(per[i].getName()+"、"); } } }
🌳运行结果:
数组声明:null、null、null、 对象实例化:张三、李四、王五、
🔭2、内部类
(1)基本定义
类内部也可以定义另一个类。如果在类Outer 的内部再定义一个类Inner,此时类Inner就称为内部类,而类Outer则称为外部类。
内部类可声明成public或private,当内部类声明成public或private时,对其访问的限制与成员变量和成员方法完全相同。
🌳声明格式:
标识符 class 外部类的名称{ / /外部类的成员 标识符 class 内部类的名称{ / /内部类的成员 } }
🌳范例:定义一个内部类
class Outer{ private String info="Hello World!"; class Inner{ public void print(){ System.out.println(info); } } public void fun(){ new Inner().print(); } } public class Test { public static void main(String[] args){ new Outer().fun(); } }
🌳运行结果:
Hello World!
可以发现,Inner类作为Outer类的内部类存在,并且在外部类的fun()方法之中直接实例化内部类的对象并调用方法print(),但是从以上代码中可以明显地发现,内部类的存在实际上己经破坏了一个类的基本结构,因为类是由属性及方法组成的,所以这是内部类的一个缺点
内部类的一个优点是可以方便地访问外部类中的私有属性。
(2)使用static定义内部类
使用static可以声明属性或方法,而使用static也可以声明内部类,用static声明的内部类变成了外部类,但是用static声明的内部类不能访问非static的外部类属性。
🌳范例:
class Outer{ private static String info="Hello World!"; static class Inner{ public void print(){ System.out.println(info); } } } public class Test { public static void main(String[] args){ new Outer.Inner().print();//访问内部类 } }
🌳运行结果:
Hello World!
如果此时属性不是static类型,则编译时将出现错误
(3)在外部访问内部类
一个内部类除了可以通过外部类访问,也可以直接在其他类中进行调用。
🌳调用的基本格式为:
外部类.内部类 内部类对象=外部类实例.new 内部类();
🌳范例:
class Outer{ private String info="Hello World!"; class Inner{ public void print(){ System.out.println(info); } } } public class Test { public static void main(String[] args){ Outer out=new Outer();//实例化外部类对象 Outer.Inner in=out.new Inner();//实例化内部类对象 in.print(); } }
🌳运行结果:
Hello World!
首先要找到外部类的实例化对象之后,才可以通过外部类的实例化对象去实例化内部类的对象。
(4)在方法中定义内部类
在方法中定义的内部类不能直接访问方法中的参数,如果方法中的参数要想被内部类所访问,则参数前必须加上final关键字
🌳范例:
class Outer{ private String info="Hello World!"; public void fun(final int temp) { class Inner { public void print() { System.out.println("类中的属性:" + info); System.out.println("方法中的参数:" + temp); } } new Inner().print(); } } public class Test { public static void main(String[] args){ new Outer().fun(30); } }
🌳运行结果:
类中的属性:Hello World! 方法中的参数:30
🔭3、实例讲解
(1)系统登录
模拟一个简单的用户登录程序
程序分析:使用初始化参数的方式输入用户名和密码,所以在程序运行之前首先必须判断输入的参数个数是否合法,如果不合法,则必须提示用户的程序执行错误,并退出程序,如果用户己经正确地输入了参数,则可以进行用户名及密码的验证。如果信息正确则显示“欢迎xxx光临!”,否则显示“错误的用户名及密码"
🌳代码如下:
class Check{ public boolean validate(String name,String password){ if(name.equals("张三") && password.equals("123")){ //验证登录信息是否正确 return true; }else{ return false; } } } class Operate{ private String[] info;//用来接收输入参数 public Operate(String[] info){ this.info=info; } public String login(){ Check check=new Check(); this.isExit(); String name=this.info[0]; String password=this.info[1]; String str; if(check.validate(name,password)){ //登录验证 str="欢迎"+name+"光临!"; }else{ str="错误的用户名和密码!"; } return str; } public void isExit(){ if(this.info.length !=2){ //判断参数的个数 System.out.println("输入的参数不正确,系统退出!"); System.out.println("格式:java LoginDemo 用户名 密码"); System.exit(1); } } } public class LoginDemo { public static void main(String[] args){ Operate oper=new Operate(args); System.out.println(oper.login()); } }
🌳程序执行命令:
java LoginDemo 张三 123
🌳程序运行结果:
欢迎张三光临!
🌳程序的调用关系:
(2)单向链表实现(一)
所谓的链表就好像火车车厢一样,从火车头开始,每一节车厢之后都连着后一节车厢(通过引用传递的方式进行实现)
🌳代码如下:
class Node{ private String data;//保存节点内容 private Node next;//保存下一个节点 public Node(String data){ this.data=data; } public String getData(){ return this.data; } public void setNext(Node next){ this.next=next; } public Node getNext(){ return this.next; } } public class LinkDemo1 { public static void main(String[] args){ Node root=new Node("火车头");//定义根节点 Node n1=new Node("车厢-A");//定义车厢 Node n2=new Node("车厢-B"); Node n3=new Node("车厢-C"); root.setNext(n1);//火车头的下一个节点是第一节车厢 n1.setNext(n2); n2.setNext(n3); printNode(root); } public static void printNode(Node node){ System.out.print(node.getData()+"\t"); if(node.getNext()!=null){ printNode(node.getNext()); } } }
🌳运行结果:
火车头 车厢-A 车厢-B 车厢-C
printNode()方法就是采用了递归的调用形式,有时也可以把这种输出形式称为迭代输出。
(3)单向链表实现(二)
如果程序要按照(一)的方式操作肯定会很麻烦,因为要由用户手工去处理各个节点的关系,这样肯定是不行的,所以最好将节点的操作进行封装,这样用户使用起来就会比较方便。
假设现在的节点操作有增加数据、查找数据、删除数据3种。如果要删除节点,则直接修改上一个节点的引用即可
🌳代码如下:
class Link{ class Node{ //节点类定义为内部类 private String data; private Node next; public Node(String data){ this.data=data; } public void add(Node newNode){ if(this.next==null){ //判断下一个节点是否为空 this.next=newNode; //如果为空,把新节点设置在next位置上 }else{ this.next.add(newNode); } } public void print(){ System.out.print(this.data+"\t"); if(this.next!=null){ //如果下一个节点不为空,让下一个节点输出 this.next.print(); } } public boolean search(String data){ //定义一个搜索方法 if(data.equals(this.data)){ //判断当前节点的名字是否与查找的一致 return true; }else{ //判断下一个 if(this.next!=null){ //下一个存在,继续查找 return this.next.search(data); //返回下一个查询结果 }else{ return false; } } } public void delete(Node previous,String data){ //删除节点 if(data.equals(this.data)){ //找到匹配节点 previous.next=this.next; //空出当前节点 }else{ if(this.next!=null){ this.next.delete(this,data); } } } } private Node root; //根节点 public void addNode(String data){ //增加节点的方法 Node newNode=new Node(data); //建立新节点 if(this.root==null){ this.root=newNode; //将第一个节点设置成根节点 }else{ this.root.add(newNode); //添加到合适的位置 } } public void printNode(){ //打印全部节点 if(this.root!=null){ //判断是否存在根节点 this.root.print(); } } public boolean contains(String name){ //判断元素是否存在 return this.root.search(name); //调用Node中search()方法 } public void deleteNode(String data){ if(this.contains(data)){ //如果节点存在,则执行删除操作 if(this.root.data.equals(data)){ //判断根节点是否满足要求 this.root=this.root.next; //将根节点之后的内容设置成根节点 }else{ this.root.next.delete(root,data);//删除节点 } } } } public class LinkDemo2 { public static void main(String[] args){ Link l=new Link(); l.addNode("A"); l.addNode("B"); l.addNode("C"); l.addNode("D"); l.addNode("E"); System.out.println("--------删除之前--------"); l.printNode(); l.deleteNode("C"); l.deleteNode("D"); System.out.println(); System.out.println("--------删除之后--------"); l.printNode(); System.out.println(); System.out.println("查询节点:"+l.contains("A")); } }
🌳运行结果:
--------删除之前-------- A B C D E --------删除之后-------- A B E 查询节点:true
以上程序对要操作的节点类进行了包装,以后用户直接调用包装后的类,即可方便地执行节点的增加、删除、查找操作。