java面向对象超详细总结(期末必备)

文章目录

面向对象:

什么是对象:

一切客观存在的物体统称为对象。

对象的组成:

1.属性 ;数据类型 变量名 [=值 ];
2.方法 ;[访问修饰符] 返回值类型 方法名字([参数列表]){代码块;}

类是什么:

1.类是对大量对象共性的抽象
2.类是创建对象的模板

类的组成:

1.属性;
2.方法;

类的创建语法

[public] class 类名{
[成员变量];
[成员方法];
}

类的使用:

使用类必须为类创建对象:

语法

类型 变量名 = new 类类型名();

如 Student stu = new Student();

调用属性:

对象名.属性名[= 值];

调用方法:

对象名.方法名();

方法的重载:

1.方法名一致,参数列表不同的方法就是方法的重载。
2.重载必须发生在同一个类里面

构造方法:构造函数,构造器

1.任何类都必须要有构造器。
2.如果类里面没有声明构造器,计算机默认提供一个午餐的构造器
3.构造器不能返回值类型。
4.构造器的方法名必须和类名一致。
5.构造方法只能跟在new的后面来创建对象.

构造器的语法:

[public] 类名([参数列表]){ 方法体; }

对象的引用:

Student s; s = new Student();
引用存储的是对象内存空间的首地址

this关键字:

  • this是一种特殊的引用,指向当前对象
  • 如果发生局部变量可以成员变量命名冲突时,可以通过this.成员变量名的方式区分实例变量和局部变量
  • 一个构造方法中需要调用同一个类的另一个构造方法,可以通过this()的方式调用,但this()必须要书写在第一行

OOP练习:

练习一

创建一个圆Circle类,为该类提供两个方法,方法一用于求圆的面积,方法二用于求圆的周长,同时为该类提供一个变量r表示半径,一个常量PI表示圆周率。
为该类提供一个无参的构造方法,用于初始化r的值为1;且提供一个有参的构造方法,参数用于初始化半径r的值

案例代码:

  public class Circle {
          //属性:
          double r;
          //常量
          final double PI=3.14;
          //方法:
          //构造方法
          public Circle(){
              r=1;//默认半径为1
          }
          //方法的重载
          public Circle(double r){
              this.r=r;
          }
          //面积
          public double area(){
              return PI*r*r;
          }
          //周长
          public double perimeter(){
              return 2*PI*r;
          }
      }

练习二

饲养员类,动物类,食物类。实现饲养员给动物喂食物。

案例代码:

 //食物类
  public class Food {
      //属性:
      String type;
      //提供构造方法
      public Food(){}
      public Food(String type){
           this.type=type;
      }
  }
  //动物类:
  public class Animal {
      //属性:
      String type;
      //构造方法:
      public Animal(){}
      public Animal(String type){
         this.type = type;
      }
      //方法:
      //吃的方法
      public void eat(Food food){
          System.out.println(type+"正在吃"+food.type);
      }
  }
  //饲养员类
  public class Feeder {
      //属性:
      Animal animal;
      Food food;
      //方法:
      //构造方法:
      public  Feeder(){}
      public Feeder(Animal animal,Food food){
            this.animal=animal;
            this.food=food;
      }
      public void feed(){
          animal.eat(food);
      }
      public static void main(String[] args) {
          //创建对象
          Food food=new Food("狗粮");
          Animal animal=new Animal("狗");
          Feeder feeder=new Feeder(animal,food);
          feeder.feed();//饲养员喂动物
      }
  }

练习三:

创建一个账户Account类,该类有id:账户号码(长整数),password:账户密码,name:真实姓名,personId:身份证号码 字符串类型,email:客户的电子邮箱,balance:账户余额.
方法:deposit: 存款方法,参数是double型的金额;
withdraw:取款方法,参数是double型的金额.
构造方法:有参和无参,有参构造方法用于设置必要的属性

案例代码:

 public class Account {
     //属性:
     long id;
     int password;
     String name;
     String personId;
     String  email;
     double balance;
     //方法:
     //构造方法
     public Account(){}
     public Account( long id,int password,String name,String personId,String  email, double balance){
            this.id=id;
            this.password=password;
            this.name=name;
            this.email=email;
            this.personId=personId;
            this.balance=balance;
     }
     //方法:
     //存款
     public void deposit(double money){
         balance+=money;//balance=balance+money;
         System.out.println("该银行卡存入"+money+"钱之后,余额是"+balance);
     }
     //取款
     public void withdraw(double money){
        //先进行判断余额是否够取出
         if(money <= balance){
             balance-=money;
             System.out.println("该银行卡取出"+money+"钱之后,余额是"+balance);
         }else{
             System.out.println("余额不足!!!!");
         }
     }
 } 

static关键字的使用:

类的组成:属性(成员变量)和方法(成员方法)

  • 成员变量分为类变量和实例变量
  • 成员方法分为类方法和实例方法
  • 类变量:使用关键字static修饰的变量
  • 类方法:使用关键字static修饰的方法

实例变量和类变量的区别:

  1. 所有该类的对象共享同一个类变量,但是每个对象都会有自己独特的实例变量
  2. 所有该类的对象都能改变类变量的值,但是每个对象只能改变自己的实例变量值
  3. 实例变量在使用前必须创建一个对象,根据对象名.变量名使用,但是类变量不需要创建对象,可以通过类名.变量名或类名.方法名直接调用。
  4. 实例方法当中可以直接调用类变量和实例变量。
  5. 类方法只能直接调用类变量,如果要想调用实例对象必须先为实例变量创建对象。
   public class StaticTest {
   	//属性
   	String name;//实例变量
   	static int age;//类变量
   	//方法
   	public void say(){//实例方法
   		System.out.println("这是我得自我介绍!!!我得名字是:"+name+"我得年龄是:"+age);
   	}
   	public static void eat(){//类方法
   		StaticTest test=new StaticTest();
   		System.out.println("我得名字是:"+test.name+"我得年龄是:"+age);
   		System.out.println("我是一个吃货");
   }
   
   public static void main(String[] args) {
   	//创建对象
           StaticTest test1=new StaticTest();
           test1.name="张三";
           test1.age=18;
           System.out.println("我得名字是"+test1.name+",我得年龄是:"+test1.age);
           StaticTest test2=new StaticTest();
           test2.age=20;
           System.out.println("我得名字是"+test2.name+",我得年龄是:"+test2.age);//
           StaticTest test3=new StaticTest();
           System.out.println("我得名字是"+test3.name+",我得年龄是:"+test3.age);
           System.out.println("StaticTest的年龄是:"+StaticTest.age);
       }
   }

静态代码块:

是一个以static为前导的代码块,一般用于为类的工作做一些初始化工作

访问修饰符的使用:

访问修饰符主要用来修饰方法和变量

访问修饰符作用范围
private本类
default本类同包下的其他类
protected本类同包下的其他类其他包下的子类
public本类同包下的其他类其他包下的子类其他包下的其他类

封装:面向对象程序设计的三大特征之一

把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类
或者对象进行操作,对不可信的类或者对象隐藏,这样的过程叫做封装。

代码演示:

  public class Student {
      //属性:1.封装:把我们的属性私有化
      private int stuNo;//学号
      private String stuName;//名字
      private int age;//年龄
      //方法:
      //2.给私有化的属性提供getter和setter方法:
      public void setStuNo(int stuNo){//给学号赋值
          if (stuNo <0){
              System.out.println("该学号是无效的,没有办法赋值!!!");
              this.stuNo=0;
          }else{
              this.stuNo=stuNo;
          }
      }
      public int getStuNo(){//获取学号
              return stuNo;
      }
      public  void setStuName(String stuName){
            this.stuName=stuName;
      }
      public String getStuName(){
          return stuName;
      }
      public  void setAge(int age){
         if(age >=0 && age <=150 ){
              this.age=age;
         }else{
             System.out.println("你的年龄是无效的。");
             this.age=0;
         }
      }
      //自我介绍:
      public  void  display(){
          System.out.println("我是一名学生,\n我的学号是:"+stuNo+"\n我的姓名是:"+stuName+"\n我的年龄:"+age);
      }
  }
  //测试类
  class  Test{
      public static void main(String[] args) {
          //创建学生对象
          Student student=new Student();
          student.setStuNo(12345);
          student.setStuName("张三");
          student.setAge(-12);
         // student.stuNo=12345;
         // student.stuName="张三";
         // student.age=-20;
          student.display();
      }
  }

实验练习:

创建一个图书Book类,该类有属性:
书名、作者、出版社、价格等。
将该类各属性进行封装,并为各属性提供getter和setter方法。
通过公有的get/set方法实现属性的访问,其中:
1、限定图书价格必须大于10,如果无效需进行提示,并强制赋值为10
2、限定作者、书名均为只读属性

案例代码:

 //图书类:
 public class Book {
        //属性:
     private String bookName;
     private String author;
     private String press;
     private double price;
     //方法:
     //构造方法
     public Book(){}
     public Book(String bookName,String author){
           this.bookName=bookName;
           this.author=author;
     }
     //提供getter和setter方法:
     public String getBookName(){
         return bookName;
     }
     public String getAuthor(){
         return author;
     }
     public void setPress(String press){
         this.press=press;
     }
     public  String getPress(){
         return press;
     }
     public void  setPrice(double price){
         if (price > 10){
             this.price=price;
         }else{
             System.out.println("你得价格是无效的!!!");
             this.price=10;
         }
     }
     public double getPrice(){
         return price;
     }
 }
 class Test1{
     public static void main(String[] args) {
          //创建图书对象
         Book book=new Book("红楼梦","曹雪芹");
         book.setPrice(-10);
         book.setPress("人民大学出版社");
          //打印图书的信息
         System.out.println("图书简介:\n书名:"+book.getBookName()+"\n作者:"+
         book.getAuthor()+"\n出版社:"+book.getPress()+"\n价格:"+book.getPrice());
     }
 }

继承:面向对象的三大特征之一

一个新类可以从现有的类派生,这样的过程叫做继承。
那么在继承的过程中,新类被称为子类,现有的类被称为父类,子类将会继承父类非私有的属性和行为。

继承的语法:

[访问修饰符] class 子类的类名 extends 父类的类名{ 成员变量;成员方法;}

继承的特点:

1.子类除了可以拥有父类非私有的属性和方法外,也可以扩展自己的属性和方法
2.Java中类的继承是单继承,也就是一个类只能有一个父类
3.Java中类的继承具有传递性。
(A继承B)(B继承了C)(A具有了B和C 所有非私有的属性和方法)
4.任何类都有父类,如果我们没有声明父类,默认继承了我们Object类.
5.子类无法继承父类的构造方法,子类在创建对象的时候都会先去调用父类的构造方法。

方法的重写:@Override

当从父类中继承过来的方法不能满足子类需要时,子类就要对方法进行重新编译。这就叫做方法的重写

重写的特点:@Override

1.只能发生在子类继承父类的子类里面。
2.子类重写的方法访问修饰符不能严于父类。
3.重写的返回值类型,方法名和参数列表都必须和父类保持一致。

重载的特点:@Overload

1.只能发生在同一个类里面
2.只要求方法名相同,参数列表不同,和其他内容没有关系。

super关键字:

1.super代表了父类的对象
2.super.属性名:子类中调用父类被隐藏的同名实例变量
3.super([参数列表]):用来调用父类的构造方法。
而且必须放在第一行。(子类一定会调用父类的构造方法)

this关键字:

1.this代表了本类的对象
2.this.属性名:当全局变量和局部变量重名,代表了全局变量
3.this([参数列表]):用来调用本类的构造方法,而且必须放在第一行。

final关键字:

final关键字可以用来修饰类、变量和方法。有不可更改或最终的含义。
final修饰的类称之为最终类,不能被继承。
final修饰的方法称之为最终方法,可以被继承不能被重写
final修饰的变量称之为常量,值不能被更改,而且必须在声明的时候进行赋值。

实验练习1:

设计一个形状类Shape,方法:求周长(girth)和求面积(area)
形状类的子类:Rect(矩形),Circle(圆形),不同的子类会有不同的计算周长和面积的方法

实验练习2:

某公司的雇员分为以下若干类:
Employee:这是所有员工总的父类,属性:员工的姓名,员工的生日月份。方法:getSalary(int month) 根据参数月份来确定工资,如果该月员工过生日,则公司会额外奖励100元。
SalariedEmployee:Employee的子类,拿固定工资的员工。属性:月薪(monthSalary)
HourlyEmployee:Employee的子类,按小时拿工资的员工,每月工作超出160小时的部分按照1.5倍工资发放。属性:每小时的工资(hourSalary)、每月工作的小时数(hour)
SalesEmployee:Employee的子类,销售人员,工资由月销售额和提成率决定。属性:月销售额(monthSales )、提成率(commissions)
BasePlusSalesEmployee:SalesEmployee的子类,有固定底薪的销售人员,工资由底薪加上销售提成部分。属性:底薪(baseSalary)。

多态:面向对象的三大特征之一

客观存在的物体的多种形态。

java中多态的实现:

1.继承或者实现关系
2.方法重写
3.向上转型

多态的实验案例:

//动物园有这些动物:狗、兔子等,
//饲养员每天都会给这些动物喂食,
//狗喜欢吃骨头、而兔子喜欢吃胡萝卜,
//通过Java程序模拟饲养员喂食
  //父类:动物类
  class Animal{
      //吃
      public void eat(){
          System.out.println("吃东西!!!");
      }
  }
  //狗类
  class Dog extends Animal{
      //吃
      public void eat(){
          System.out.println("吃骨头!!!!");
      }
      //看门
      public void seeDoor(){
          System.out.println("吃饱了之后去看门!!!!");
      }
  }
  //兔子类
  class Rabbit extends Animal{
       //吃
      public void eat(){
          System.out.println("吃红萝卜!!!!");
      }
      //睡觉
      public void sleep(){
          System.out.println("吃饱了之后就睡觉!!!!");
      }
  }
  // 猫
  class Cat extends Animal{
      //吃
      public void eat(){
          System.out.println("吃鱼!!!");
      }
      //抓耗子
      public void catchMouse(){
          System.out.println("吃饱之后去抓耗子!!!!");
      }
  }
  //饲养员的类
  class Feeder{
      //喂食
      public void  feed(Animal animal){
          animal.eat();
          //向下转型
           if(animal instanceof Dog){
               //向下转型(强制转换)
               Dog dog=(Dog) animal;
               dog.seeDoor();
           }else if(animal instanceof Rabbit){
               Rabbit rabbit =(Rabbit) animal;
               rabbit.sleep();
           }else if(animal instanceof Cat){
               Cat cat=(Cat) animal;
               cat.catchMouse();
           }
      }
     /* public void feed(Dog dog){
          dog.eat();
      }
      public void feed(Rabbit rabbit){
          rabbit.eat();
      }
      public void feed(Cat cat){
          cat.eat();
      }*/
  }
  class Test{
      public static void main(String[] args) {
          //饲养员给动物喂食物的过程
          Feeder zhangSan=new Feeder();
          //创建动物对象:向上转型  父亲:教毛概 儿子:教经济学  看电影
          Animal dog=new Dog();  //   父亲 = new  儿子();
                                 //   讲课:教经济学
          Animal rabbit=new Rabbit();//回家:向下转型
          Animal cat=new Cat();
         // Dog dog=new Dog();
         // Rabbit rabbit=new Rabbit();
          zhangSan.feed(rabbit);
      }
  }

多态的优势:

1.提高代码的重用
2.降低耦合度

instanceof运算符:

判断对象是否属于某个类。

import关键字:

用来引入我们某些类。

import 包.类名;

导入包的实验案例:

  • 猜数字的小案例:
  • 随机数产生一个答案,通过键盘输入进行猜测:
    猜测的数过大:提示猜测的数字过大,重新猜
    猜测的数过小:提示猜测的数字过小,重新猜
    猜对了:提示恭喜过关!!!
public class ImportTest {
    //随机数产生一个答案
    private static int num;
    //静态代码块:
    static {
        Random random=new Random();
        num = random.nextInt(100);
    }
    public static void main(String[] args) {
        //创建键盘输入的类
        Scanner sc=new Scanner(System.in);
        //提示语句
        System.out.println("请输入您猜测的答案:");
        while(true) {
            //接收键盘输入
            int i = sc.nextInt();
            //判断猜测的结果是否正确
            if (i > num) {
                System.out.println("猜大了,请重新猜!!!");
            }else if(i < num){
                System.out.println("猜小了,请重新猜!!!");
            }else{
                System.out.println("恭喜您答对啦!!!欢迎过关!!!");
                break;//跳出循环
            }
        }
    }
}

包就是用来将Java中类和接口等进行分类管理的工具,类似于操作系统中的目录

包的声明:package

package 包名;

包名的前半部分一般使用倒置的域名,后半部分一般采用该包下类分类名(或者功能名)。
如:
package com.java.util;
package com.java.dao;
包的声明必须是整个类文件的第一行语句

抽象类和抽象方法

抽象方法:abstract抽象的.

对于某些方法没有具体的实现过程,而且子类肯定回重写这个方法,出于对项目的优化,把方法声明称抽象方法

抽象方法的声明:

[修饰符] abstract 返回值类型 方法名([参数列表]);
注意:因为抽象方法无法确定具体执行的功能,所有抽象方法没有方法体,需要在小括号后加上分号

抽象类:abstract抽象的

对于我们的抽象方法,普通的类没有办法声明,需要把我们的类也声明为抽象的 。这样类叫做抽象类.

抽象类的语法:

[修饰符] abstract class 类名 [extends 父类名]{类体}

抽象类优点:优化代码,优化性能.

1.存在抽象方法的类后一定是抽象类。
2.抽象类可以放普通方法。(抽象类也可以只有普通方法)
3.抽象类不可以直接创建对象。
如果想要创建对象只能创建子类的对象
4.子类继承了抽象类,必须重写抽象类里面所有的抽象方法。
5.抽象类也可以使用多态。

抽象类的实验案例练习:

设计一个形状类(抽象类)Shape,方法:求周长和求面积
形状类(抽象类)的子类:Rect(矩形),Circle(圆形),Square(正方形),不同的子类会有不同的计算周长和面积的方法,创建三个不同的形状对象,放在Shape类型的数组里,分别打印出每个对象的周长和面积

接口:

接口不仅仅是程序开发过程中“约定”,更是更加抽象化的抽象类.

接口的声明语法:interface关键字

[访问修饰符] interface 接口名{
[public] [static] [final] 数据类型 常量名字 =值;
[public] [abstract] 返回值类型 方法名([参数列表]);
}

JDK1.8以后特性:

//使用默认修饰符修饰的方法:
default  void  say(){
	System.out.println("JDK1.8的特性,可以使用默认方法!!!");
}

//还可以声明静态方法:
public  static void  display(){
    System.out.println("jdk1.8以后接口可以使用静态方法!!!!");
}

接口的使用:implements关键字

[访问修饰符] class 类名 implements 接口名{}

接口的特点:

1.接口不能创建对象,可以创建实现类的对象.
2.实现类实现接口的时候,必须重写接口里面所有的抽象方法。
3.实现类实现接口的时候可以实现多个接口.(多实现)
4.接口可以继承接口.一个子接口可以继承多个父接口(多继承)

接口的优势:

1.提高程序的重用性
2.提高程序可扩展性
3.降低程序的耦合度
4.接口实现了多继承.

接口的使用案例:

此时有一个学生张三:包含了学号,包含姓名,喜欢学习线性代数,喜欢抽烟,喜欢喝酒,喜欢打游戏.


public abstract class Student {
    //属性:
    private  int stuNo;
    private String stuName;
    //方法:
    //构造方法
    public Student(){}
    public Student(int stuNo,String stuName){
        this.stuNo=stuNo;
        this.stuName=stuName;
    }
    //提供getter和setter方法
    public void setStuNo(int stuNo){
        this.stuNo=stuNo;
    }
    public int getStuNo(){
        return stuNo;
    }
    public void setStuName(String stuName){
        this.stuName=stuName;
    }
    public String getStuName(){
        return stuName;
    }
    //学习的方法
    public abstract void study();
}
//接口代表能力
interface Smoking{
    //抽烟
    void smoke();
}
interface Drinking{
    //喝酒
    void drink();
}
interface  Game{
    //游戏
    void play();
}
//创建具有功能特点的学生
class ZhangSan extends Student implements Smoking,Drinking,Game{
    //构造方法
    public ZhangSan(){}
    public ZhangSan(int stuNo,String stuName){
        super(stuNo,stuName);
    }
    @Override
    public void study() {
        System.out.println(getStuName()+"喜欢学习线性代数!!");
    }
    @Override
    public void smoke() {
        System.out.println("喜欢喝飞天茅台!!!!");
    }
    @Override
    public void drink() {
        System.out.println("喜欢抽冬虫夏草!!!!");
    }

    @Override
    public void play() {
        System.out.println("喜欢玩儿LOL");
    }
}
//有一个学生李四:不喜欢学习,喜欢玩儿游戏
 class LiSi extends Student implements Game{
      //构造方法
      public LiSi(){}
      public LiSi(int stuNo,String stuName){
           super(stuNo, stuName);
      }
      @Override
      public void study() {
          System.out.println(getStuName()+"不喜欢学习,就喜欢睡觉!!");
      }
      @Override
      public void play() {
          System.out.println("喜欢玩植物大战僵尸!!!");
      }
  }
  class Test{
      public static void main(String[] args) {
          //创建张三这个学生
          ZhangSan zhangSan=new ZhangSan(1001,"张三");
          zhangSan.study();//学习
          zhangSan.smoke();//抽烟
          zhangSan.drink();//喝酒
          zhangSan.play();//玩游戏
          System.out.println();
          LiSi liSi=new LiSi(1002,"李四");
          liSi.study();
          liSi.play();//玩游戏
      }
  }

接口的专项练习:

1.普通的手机(CommonHandset),可以发短信,通电话。随着发展,智能手机(AptitudeHandset ),增加了功能:音频、视频播放(PlayWiring )、拍照(TheakePictures )、上网(Network )

     //手机:
     public abstract class HandSet {
         //属性:
         private String type;//型号
         private String brand;//品牌
         //方法:
          //提供构造方法
         public HandSet(){}
         public HandSet(String type,String brand){
             this.type=type;
             this.brand=brand;
         }
         //提供getter和setter方法
         public void setType(String type){
              this.type=type;
         }
         public String getType(){
             return type;
         }
         public  void  setBrand(String brand){
             this.brand=brand;
         }
         public String getBrand(){
             return brand;
         }
         //描述手机基本信息
         public void display(){
             System.out.println("这是一款型号为"+type+"的"+brand+"手机......");
         }
         //打电话
         public abstract void call();
         //发短信
         public abstract  void sendInfo();
     }
     //音频和视频的播放:
     interface PlayWiring{
         //播放功能:
         void play(String content);
     }
     //拍照接口
     interface  TheakePictures{
         //拍照功能
         void takePicture();
     }
     //联网:
     interface  Network{
         //联网功能
         void netWorkConn();
     }
     //创建手机类:
     class CommonHandset extends HandSet implements PlayWiring{
         //提供构造方法:
         public  CommonHandset(){}
         public CommonHandset(String type,String brand){
              super(type, brand);
         }
         @Override
         public void call() {
             System.out.println("开始语音通话......");
         }
         @Override
         public void sendInfo() {
             System.out.println("发送文字信息......");
         }
         @Override
         public void play(String content) {
             System.out.println("开始播放音乐《"+content+"》.....");
         }
     }
     //智能手机:
     class AptitudeHandset extends HandSet implements PlayWiring,Network,TheakePictures{
        //构造方法:
         public  AptitudeHandset(){}
         public  AptitudeHandset(String type,String brand){
             super(type, brand);
         }
         @Override
         public void call() {
             System.out.println("开始视频通话......");
         }
         @Override
         public void sendInfo() {
             System.out.println("开始发送带有文字和图片的信息.....");
         }
     
         @Override
         public void play(String content) {
             System.out.println("开始播放视频《"+content+"》.....");
         }
     
         @Override
         public void takePicture() {
             System.out.println("咔嚓.......拍照成功!!!!");
         }
     
         @Override
         public void netWorkConn() {
             System.out.println("已经启动网络连接......");
         }
     }
     //测试类:
     class Test{
         public static void main(String[] args) {
             //购买两款手机
             CommonHandset commonHandset=new CommonHandset("G502c","索尼爱立信");
             commonHandset.display();//出厂信息
             commonHandset.play("热雪");//播放音乐
             commonHandset.sendInfo();//发短信
             commonHandset.call();//打电话
             AptitudeHandset aptitudeHandset=new AptitudeHandset("I9100","HTC");
             aptitudeHandset.display();//出厂信息
             aptitudeHandset.netWorkConn();//链接网络
             aptitudeHandset.play("小时代");//播放视频
             aptitudeHandset.takePicture();//拍照
             aptitudeHandset.sendInfo();//发信息
             aptitudeHandset.call();//打电话
         }
     }

2.设计一个台灯类Lamp其中台灯有灯泡这个属性,还有开灯(on)这个方法,设计一个灯泡类,其中有红灯泡(RedBuble) 和绿灯泡(GreenBuble),他们都有一个发亮的方法,请设计出一段代码可以使台灯开启灯泡发亮,并且保证替换不同种类的灯泡台灯类代码不被修改。

//灯泡接口
    interface Buble{
        //发光:
        void light();
    }
    //红灯泡
    class RedBuble implements Buble{
        @Override
        public void light() {
            System.out.println("发红光!!!!!");
        }
    }
    //绿灯泡
    class GreenBuble implements Buble{
        @Override
        public void light() {
            System.out.println("发绿光");
        }
    }
    //台灯类
    public class Lamp {
        //属性:
        private Buble buble;
        //提供构造方法:
        public Lamp(){}
        public Lamp(Buble buble){
            this.buble=buble;
        }
        //提供gterter和setter方法:
        public  void  setBuble(Buble buble){
            this.buble=buble;
        }
        public Buble getBuble(){
            return buble;
        }
        //开关:
        public  void  on(){
            buble.light();
        }
    }
    //测试类:
    class TestLamp{
        public static void main(String[] args) {
            //购买灯泡:多态
            Buble buble1=new RedBuble();
            Buble buble2=new GreenBuble();
            //组装台灯
            Lamp lamp=new Lamp(buble2);
            //开灯
            lamp.on();
        }
    }
//抽象类方式
//1.	在IDEA项目中创建对应的一个灯泡类(Buble) :灯泡类中没有属性,只有一个发光的方法light();根据不同的灯泡显示不同的颜色。
abstract class Buble {
    abstract void light();
}
//2.	设计一个红灯泡(RedBuble)类:他满足了灯泡类的要求,并根据灯泡的颜色重写了发光的方法。
class RedBuble extends Buble{
    @Override
    void light() {
        System.out.println("发红光……");
    }

}
class GreenBuble extends Buble{
//3.	设计一个绿灯泡(GreenBuble)类:他满足了灯泡类的要求,并根据灯泡的颜色重写了发光的方法。
    @Override
    void light() {
        System.out.println("发绿光……");
    }
}
class Lamp{
//4.	设计台灯类(Lamp):该类含有一个成员变量灯泡(灯泡类型)。对成员变量进行封装。
    private Buble buble;
//5.	声明一个没有参数的构造方法,重载一个构造方法,用于为台灯的灯泡赋值;
    public Lamp(){}
    public Lamp(Buble buble){
        this.buble = buble;
    }
//6.	为私有的灯泡提供getter和setter方法,用于赋值和取值。

    public void setBuble(Buble buble) {
        this.buble = buble;
    }

    public Buble getBuble() {
        return buble;
    }

//7.	声明一个开灯(on)的方法,用于打开台灯后显示灯泡的颜色的功能
    public void on(){
        buble.light();
    }
}
class Test{
//8.	创建一个测试类:计出一段代码可以使台灯开启灯泡发亮,并且保证替换不同种类的灯泡台灯类代码不被修改.
    public static void main(String[] args) {
        Buble red = new RedBuble();
        Buble green = new GreenBuble();

        Lamp lamp1 = new Lamp(red);
        lamp1.on();
        Lamp lamp2 = new Lamp(green);
        lamp2.on();
    }
}

3.墨盒和纸张的规格是一种约定 。打印机需要遵守这些约定。
用面向接口编程的方式开发,制定墨盒、纸张的约定或标准,打印机厂商使用墨盒、纸张的标准开发打印机,其他厂商按照墨盒、纸张的标准生产墨盒、纸张

      //墨盒的接口
      public interface InkBox {
           //获取墨盒的颜色
            String getColor();
      }
      //纸张的接口
      interface Paper{
           //获取纸张的大小
          String getSize();
      }
      //墨盒类
      class ColorInkBox implements InkBox{
          @Override
          public String getColor() {
              return "彩色";
          }
      }
      class HBInkBox implements  InkBox{
          @Override
          public String getColor() {
              return "黑白";
          }
      }
      //纸张
      class A4Paper implements Paper{
          @Override
          public String getSize() {
              return "A4";
          }
      }
      class B5Paper implements Paper{
          @Override
          public String getSize() {
              return "B5";
          }
      }
      //打印机
      class DaYinJi{
          //属性:
          private InkBox inkBox;
          private Paper paper;
          //构造方法:
          public  DaYinJi(){}
          public DaYinJi(InkBox inkBox,Paper paper){
              this.inkBox=inkBox;
              this.paper=paper;
          }
          //提供getter和setter方法
          public void setInkBox(InkBox inkBox){
              this.inkBox=inkBox;
          }
          public InkBox getInkBox(){
              return inkBox;
          }
          public  void  setPaper(Paper paper){
                this.paper=paper;
          }
          public Paper getPaper(){
              return paper;
          }
          //打印机工作
          public void display(){
              System.out.println("使用"+inkBox.getColor()+"墨盒在"+paper.getSize()+"进行工作");
          }
      }
      //创建测试类:
      class TestDaYinJi{
          public static void main(String[] args) {
              //购买墨盒:多态
              InkBox inkBox1=new ColorInkBox();
              InkBox inkBox2=new HBInkBox();
              //购买纸张:多态
              Paper a4=new A4Paper();
              Paper b5=new B5Paper();
              //组装打印机
              DaYinJi daYinJi=new DaYinJi(inkBox2,b5);
             //打印:
              daYinJi.display();
          }
      } 

内部类:

在一个类中定义一个类。
举例:在一个类A的内部定义一个类B, 类B就被称为内部类

内部类的声明语法:

[public] class 外部类名{
[public] class 内部类{
}
}

内部类的访问特点:

内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象

案例:

//外部类
     public class Outter {
         //属性:
         private  String name="张三";
          //内部类:
         public  class Inner{
              //属性:
              public int age=18;
              //方法:
              //内部类调用外部类可以直接访问
              public void say(){
                  System.out.println("我是一个内部类!!!!我得外部类的名字是:"+name);
                  //调用外部类的方法:
                  display();
              }
          }
         //方法:
         public void  display(){
             //外部类调用内部类必须先创建对象
             Inner in=new Inner();
             System.out.println("我是一个外部类!!我得内部类的年龄是:"+in.age);
             in.say();
         }
     }

内部类的使用语法:

​ 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
​ 举例:Outer.Inner oi = new Outer().new Inner();

案例

//结合上面
class Test{
         public static void main(String[] args) {
             //创建外部类的对象
             Outter out=new Outter();
             //创建内部类的对象:
             Outter.Inner in=new Outter().new Inner();
             Outter.Inner in1=out.new Inner();
         }
     }

私有化的内部类:

将一个类,设计为内部类的目的,大多数都是不想让外界去访问,所以内部类的定义应该私有化,私有化之后,再提供一个可以让外界调用的方法,方法内部创建内部类对象并调用。

     //外部类1
         class Outter1{
             //私有化内部类:
             private class Inner1{
                 //方法:
                 public void  show(){
                     System.out.println("我是一个私有化的内部类!!!!");
                 }
             }
         //获取内部类的方法:
         public void getInner(){
             Inner1 in1=new Inner1();
             in1.show();
         }
     }
     class Test1{
         public static void main(String[] args) {
             //使用内部类:
              Outter1 out=new Outter1();
              out.getInner();
         }
     }

局部内部类:

局部内部类定义:
局部内部类是在方法中定义的类。(只能在方法内部使用)

局部内部类的访问方式:

局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用,该类可以直接访问外部类的成员,也可以访问方法内的局部变量

    //外部类:
    public class Outter2 {
       //属性:全局变量
        private String name="李四";
        //方法:
        public  void  method(){
            //属性:局部变量
            int age=18;
            //局部内部类:
            class Inner2{
                 //方法:
                public  void  display(){
                    System.out.println("我是一个局部的内部类!!!外部类的名字是:"+name);
                    System.out.println("我的外部类的局部变量是:"+age);
                }
            }
            //创建内部类的对象:
            Inner2 in2=new Inner2();
            in2.display();
        }
    }

匿名内部类:

存在一个类或者接口,这里的类可以是具体类也可以是抽象类 .

匿名内部类的格式:

new 类名 ( ) { 重写方法 } new 接口名 ( ) { 重写方法 }

匿名内部类的本质:

是一个继承了该类或者实现了该接口的子类匿名对象,匿名内部类可以通过多态的形式接受.
匿名内部类在创建完对象之后可以在对象的后面直接通过.方法名()直接调用方法

     //动物类
     public abstract class Animal {
         //吃的方法:
         public abstract   void eat();
     }
     /*class Dog extends Animal{
         @Override
         public void eat() {
             System.out.println("吃骨头!!!");
         }
     }*/
     class  Test2{
         public static void main(String[] args) {
             //创建对象:
             //匿名内部类
             new Animal(){
                 @Override
                 public void eat() {
                     System.out.println("吃骨头!!!!");
                 }
             }.eat();
             new Animal() {
                 @Override
                 public void eat() {
                     System.out.println("吃鱼!!!!!");
                 }
             }.eat();
         }
     }

匿名内部类的案例练习:

定义一个接口Jumpping,该接口定义了跳高的方法。
如果我们的Cat类实现了此接口,则可以完成跳高动作,如果我们的Dog类实现了此接口,则也可以完成跳高动作。现有操作类JumppingOperator来完成动物的跳高操作。分别传递Cat对象或者Dog对象都可进行跳高。请分别使用多态和匿名内部类来实现设计操作。

public interface Jumpping1 {
    //定义跳高的方法:
    void jump();
}
//比赛类:
class JumppingOperator1 {
    //跳高比赛:多态
    public void operator(Jumpping j) {
        j.jump();//跳高的方法
    }
    public static void main(String[] args) {
        //创建比赛的对象
        JumppingOperator1 o=new JumppingOperator1();
        o.operator(new Jumpping(){
            @Override
            public void jump() {
                System.out.println("狗可以跳高啦!!!!");
            }
        });
        o.operator(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("猫可以跳高啦");
            }
        });
    }
}

Lambda表达式(闭包):

Lambda 表达式,也可称为闭包, 它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑

Lambda简介:

Lambda 表达式是一个匿名函数。简单来说,这是一种没有声明的方法,即没有访问修饰符,返回值声明和名称。
Lambda表达式是一种函数式思想的体现,这种表达式只针对有一个抽象方法的接口实现.

Lambda表达式的语法:

语法:([参数列表])->{代码块;}
形式参数:
如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
->:由英文中画线和大于符号组成,固定写法。代表指向动作
代码块: 是我们具体要做的事情,也就是以前我们写的方法体内容

Lambda表达式的前提:

有一个接口;
接口中有且仅有一个抽象方法;
@FunctionalInterface

注解:标注了函数式接口.代表接口里面只有一个函数

Lambda表达式的案例代码:

//接口:
@FunctionalInterface//注解:标注了函数式接口.代表接口里面只有一个函数
public interface Animal {
	//吃的方法:
	void eat();
}
//实现类:
class Dog implements Animal{
	@Override
	public void eat() {
    	System.out.println("这是多态的实现:");
		System.out.println("一天一水果,疾病远离我!!!!");
	}
}
//饲养员
class Feeder{
    //喂:静态的
    public static void feed(Animal animal){
        animal.eat();
    }
    public static void main(String[] args) {
        //模拟饲养喂动物
        //多态:创建动物的对象
        Animal dog=new Dog();
        feed(dog);
        //匿名内部类
        feed(new Animal(){
            @Override
            public void eat() {
                System.out.println("匿名内部类实现:");
                System.out.println("一天一水果,疾病远离我!!!!");
            }
        });
        //Lambda表达式:
        feed(()->{
            System.out.println("Lambda表达式实现:");
            System.out.println("一天一水果,疾病远离我!!!!");
        });
    }
}

Lambda表达式的案例练习:

  1. 不需要参数,返回值为 5:() -> 5
//函数式接口
@FunctionalInterface
public interface Num {
    //声明一个抽象方法:
    int getNum();
}
//测试类:
class TestNum{
    //声明使用接口的方法:
    public static void useNum(Num num){
        int value=num.getNum();
        System.out.println("这是我获取到的值:"+value);
    }
    //主方法:
    public static void main(String[] args) {
        //匿名内部类:
        useNum(new Num(){
            @Override
            public int getNum() {
                return 5;
            }
        });
        //Lambda表达式
        useNum(()->{return 5;});
        useNum(()->5);
    }
}

2.接收一个参数(数字类型),返回其2倍的值 :(x) -> 2 * x

//函数式接口:
@FunctionalInterface
public interface Num2 {
    //声明一个方法:
    int getNum2(int num);
}
//测试类:
class TestNum2{
    //声明使用函数式接口的方法
    public static void  useNum2(Num2 num2,int num){
        int value = num2.getNum2(num);
        System.out.println("我的参数值的2倍是:"+value);
    }
    //主方法:
    public static void main(String[] args) {
        //匿名内部类
        useNum2(new Num2() {
            @Override
            public int getNum2(int num) {
                return 2*num;
            }
        },8);//16
        //Lambda表达式:
        useNum2((aa)->{return 2*aa;},10);//20
        useNum2((aa)->2*aa,10);
    }
}

3.接受2个参数(数字),并返回他们的差值 :(x, y) -> x – y

//函数式接口
@FunctionalInterface
public interface Num3 {
    int getNum3(int x,int y);
}
//测试类:
class TestNum3{
    //声明一个使用的方法:
    public static void  useNum3(Num3 num3,int x,int y){
        int value= num3.getNum3(x,y);
        System.out.println("x-y="+value);
    }
    //主方法
    public static void main(String[] args) {
        //Lambda表达式:
        useNum3((x,y)->{return x-y;},45,31);
        useNum3((x,y)->x-y,45,31);
    }
}

4.接受2个参数(数字),并返回他们的差值 :(x, y) -> x + y

//接受2个参数(数字),并返回他们的差值  :(x, y) -> x – y
@FunctionalInterface
public interface Num4 {
    //    方法
    int getNum4(int x,int y);
}

class TestNum4{
    //    函数式接口的方法
    public static void useNum4(Num4 num4,int x,int y){
        int val = num4.getNum4(x,y);
        System.out.println("我的参数值的x+y是"+val);
    }

    public static void main(String[] args) {
//        匿名内部类
        useNum4(new Num4() {
            @Override
            public int getNum4(int x,int y) {
                return x+y;
            }
        },5,2);
//      lambda表达式
        useNum4((num1,num2) -> {return num1+num2;},10,3);
        useNum4((num1,num2) -> num1+num2,10,3);
    }
}

5.接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)

上课讲的:

//函数式接口:
@FunctionalInterface
public interface String {
    void getStr(java.lang.String str);
}
//测试类:
class TestString{
    //声明一个调用的方法:
    public static void  useString(String str, java.lang.String s){
        str.getStr(s);
    }
    public static void main(java.lang.String[] args) {
        //Lambda表达式:
        useString((s)->{
            System.out.println(s);
        },"一天一水果,疾病远离我!!!!");
    }
}

自己写的:

//函数式接口
@FunctionalInterface
public interface Str{
    void getStr(String str);
}

class TestStr{
//    调用方法
    public static void useStr(Str str,String s){
        str.getStr(s);
    }

    public static void main(String[] args) {
//        lambda表达式
        useStr((s)->{
            System.out.println(s);
        },"一天一水果,疾病远离我");
    }
}

Lambda表达式调用类里面的静态方法:

如果是静态方法,则是ClassName::methodName。如 Object ::equals

@FunctionalInterface
public interface Num {
    //获取参数值的方法:
    int getNum(int num);
}
//创建类:
class Static{
    //静态方法:获取任意数字的绝对值
    public static int abs(int num){
        if(num>0){
            return num;
        }else{
            return -num;
        }
    }
}
//测试类:
class TestNum{
    //声明一个方法:使用我们的函数式接口
    public static void useNum(Num num,int n){
        int value = num.getNum(n);
        System.out.println("我的value是:"+value);
    }
    public static void main(String[] args) {
        //使用lambda表达式来调用方法:
        useNum((num)->Static.abs(num),-12);
        //调用方法的简化写法:
        useNum(Static::abs,-12);
    }
}

Lambda表达式调用类里面的实例方法:

如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;

@FunctionalInterface
public interface Num {
    //获取参数值的方法:
    int getNum(int num);
}
//创建类:
class Static{
    //实例方法:获取任意数字的绝对值
    public int abs(int num){
        if(num>0){
            return num;
        }else{
            return -num;
        }
    }
}
//测试类:
class TestNum{
    //声明一个方法:使用我们的函数式接口
    public static void useNum(Num num,int n){
        int value = num.getNum(n);
        System.out.println("我的value是:"+value);
    }
    public static void main(String[] args) {
        //使用lambda表达式来调用方法:
        useNum((num)->new Static().abs(num),-12);
        //调用方法的简化写法:
        useNum(new Static()::abs,-12);
    }
}

lambda表达式调用构造方法:

构造函数.则是ClassName::new

@FunctionalInterface
public interface String1 {
    //获取Str的对象
    Str getStr(String str);
}
class Str{
    private String name;
    public Str(){}
    public Str(String str){
        this.name=str;
    }
    //打印的方法
    public void display(){
        System.out.println("我得名字是:"+name);
    }
}
//测试类:
class TestStr{
    //声明一个使用接口的方法:
    public static  Str useStr(String1 string1,String str){
        Str s=string1.getStr(str);
        return s;
    }

    public static void main(String[] args) {
        //调用使用接口的方法:
        Str str1=useStr((str)->new Str(str),"张三");
        //使用渐变写法创建对象
        Str str2=useStr(Str::new,"李四");
        str1.display();
        str2.display();
    }
}

异常:

异常是程序在编译或运行过程出现的例外,这些例外在有的可以避免有的却无法避免

异常的分类:

在这里插入图片描述

  1. Throwable(总异常):包含下面两种情况:
  • error(错误):程序运行的代码问题,无法通过编码处理,只能修改代码。 byte b=128;

  • exception(异常):程序运行过程中的列外情况,可以通过编码进行处理。(包含以下两种情况:)

    • 编译期异常:编写代码的时候直接报错,不可避免,必须进行处理。处理完继续编写

      • ParseException 解析异常
      DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      String date="1998-12-15 12:13:14";
      df.parse(date);
      
    • ​ 运行时异常:编写代码的时候没有报错,但是在运行的时候,控制面板会报错。需要手动捕获。

  1. 常见的运行时异常:
  • NullPointerException 空指针异常

    //声明String对象:	
    String name=null;
    System.out.println(name.hashCode());
    
  • ArithmeticException 算术异常

    System.out.println(12/0);
    
  • ArrayIndexOutOfBoundsException数组下标越界异常

    int [] aa=new int [5];
    System.out.println(aa[5]);
    
  • ClassCastException类型转换异常

    Object object=new Integer(10);
    String str=(String) object;
    

异常处理:

  1. try、catch、finally关键字捕获异常:

    try{
        //可能会出现异常的代码
    }catch(ParseException  e){
        //捕获执行的代码
    }finally{
        //不管是否发生异常都要执行的代码
    } 
    
  2. 异常的捕获

    1. 语法格式
      try{
      可能产生异常对象的语句块。
      }catch(异常类型 引用名){
      针对当前异常类型对象的处理语句块;
      }
      … (可以写多个catch)
      finally{
      无论是否发生异常都应该执行的语句块。
      }

    2. 注意事项
      当捕获异常的结构中有多个catch分支时,切记小范围的异常类型放在大范围的异常类型上面
      懒人的写法:
      catch(Exception e){…}

    3. 执行流程
      try{
      a;
      b;可能产生异常的语句
      c;
      }catch(Exception e){
      e;
      }finally{
      f;
      }

    当没有产生异常的时候,程序的执行流程时:a b c f
    当产生异常时,程序执行流程是 a b e f

  3. throws关键字声明抛出异常:

    (1)基本概念
    在某些特殊的场合中,当产生异常后却无法直接处理的/不想处理时,此时就可以将异常转移给当前方法的调用着,这就叫异常的抛出。

    (2)语法格式

    返回值类型 方法名称(形参列表) throws 异常类型{...............}

    (3)方法重写的原则
    a.要求方法名相同、参数列表相同、返回值类型也相同,从jdk1.5开始允许返回子类类型。
    b.访问权限不能变小,可以相同或者变大。
    c.不能抛出更大的异常

    注意:
    子类中重写以后的方法可以选择抛出与父类一样的异常、更小的异常、不抛出异常,但是不能抛出更大的异常、不同的异常。

  4. 自定义异常
    (1)自定义异常的由来
    java官方库中虽然提供了大量的异常类,但不足以描述现实生活中所有的异常情况,当出现官方库中没有描述
    的异常情况时候就需要程序员自定义异常类加以描述,使得异常信息更加具备针对性和可读性。

    (2)自定义异常的流程
    a.自定义类继承Exception类或者Exception类的子类
    b.提供两个版本的构造方法,一个是无参构造方法,另一个是字符串做参数的构造方法

  5. 异常对象的抛出
    throw new 异常类型()
    例如:
    throw new Exception()

  6. throw和throws的区别?
    throws
    用在方法声明后面,跟的是异常类名
    可以跟多个异常类名,用逗号隔开
    表示抛出异常,由该方法的调用者来处理
    throws表示出现异常的一种可能性,并不一定会发生这些异常
    throw
    用在方法体内,跟的是异常对象名
    只能抛出一个异常对象名
    表示抛出异常,由方法体内的语句处理
    throw则是抛出了异常,执行throw则一定抛出了某种异常

  7. throws:异常的抛出,是处理异常的一种方式。

  8. throw:创建异常,自定义异常的方法。

自定义异常:自己定义的报错情况

继承自Exception的自定义异常:编译期异常
继承自RuntimeException的自定义异常:运行时异常


public class BalanceException extends Exception {
    //提供构造方法:
    public BalanceException() {}

    public BalanceException(String message) {
        super(message);
    }
}

class Account {
    //属性:
    private double balance;

    //提供构造方法:
    public Account() {
    }

    public Account(double balance) {
        this.balance = balance;
    }

    //方法:
    public void setBalance(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }

    //定义一个取款的方法:
    public void whitdraw(double money) throws BalanceException {
        if (money > balance) {
            //发生异常
            throw new BalanceException("余额不足!!!!");
        } else {
            balance -= money;
            System.out.println("取款后的余额是:" + balance);
        }
    }
}

class Test {
    public static void main(String[] args) throws BalanceException {
        //创建对象
        Account account = new Account(500);
        try {
            account.whitdraw(600);
        }catch (BalanceException e){
            account.setBalance(10000);
            account.whitdraw(600);
        }
    }
}

自定义异常案例:

自定义一个学生类,属性有 姓名 年龄,如果用户在给学生年龄赋值时,年龄小于0抛出一个AgeLT0Exception,大于150 抛出一个AgeGT150Exception

//自定义异常
//运行时异常
public class AgeLT0Exception extends RuntimeException {
    public AgeLT0Exception(){}
    public AgeLT0Exception(String message){
        super(message);
    }
}
//编译期异常
class AgeGT150Exception extends Exception{
    public AgeGT150Exception(){}
    public AgeGT150Exception(String message){
        super(message);
    }
}
//学生类:
class Student{
    //属性:
    private String stuName;
    private int age;
    //方法:getter和setter方法:
    public void setStuName(String stuName){
        this.stuName=stuName;
    }
    public String getStuName(){
        return stuName;
    }
    public int getAge(){
        return age;
    }
    // 抛出异常
    public void setAge(int age) throws AgeGT150Exception {
        if(age < 0){
            //报异常
            throw new AgeLT0Exception("年龄小于0 !!!!");
        }else if(age > 150){
            //报异常
            throw new AgeGT150Exception("年龄大于150!!!");
        }else{
            this.age=age;
        }
    }
}
//测试类:
class TestStu{
    //抛出异常
    public static void main(String[] args) throws AgeGT150Exception {
        //创建学生类的对象:
        Student stu=new Student();
        stu.setAge(156);
    }
}

集合

集合(collection)有时又称为容器,它是一个对象,能将具有相同性质的多个元素汇聚成一个整体,集合被用于存储、获取、操纵和传输聚合的数据.

JAVA集合框架图:

请添加图片描述
请添加图片描述
请添加图片描述

集合接口:

Collection接口:

  1. int size():获取集合的长度.

  2. boolean isEmpty():判断集合是否为空

  3. boolean add(E element):给集合添加元素。

  4. boolean remove(Object o):删除指定元素

  5. Iterator iterator():返回在集合元素上进行迭代的迭代器

  6. void clear():清空集合。

List集合接口:

  • 特点:
  1. 有序的集合。
  2. 可以包含重复的数据.
  • 常用方法:
    E get(int index):根据我们的下标获取指定元素。
    E remove(int index):移除指定下标的集合。
  • 其他:
    <泛型>:指定集合存放的数据类型.

list集合对象案例:

public class TestList {
    public static void main(String[] args) {
        //创建list集合对象:
        List<String> list=new ArrayList<>();
        //往集合中存放数据:
        //size():获取集合的长度.
        int length= list.size();
        System.out.println("集合长度是:"+length);
        //boolean isEmpty():判断集合是否为空
        boolean bo=list.isEmpty();
        System.out.println("集合是否为空:"+bo);
        //boolean add(E element):给集合添加元素。
        boolean bo1=list.add("张三");//0
        list.add("张三");//1
        list.add("张三2");//2
        list.add("张三3");//3
        list.add("张三4");//4
        list.add("张三5");
        System.out.println("添加元素:"+bo1);
        System.out.println("集合长度是:"+list.size());
        //集合的遍历:
        //for循环遍历:
        System.out.println("---for循环遍历---");
        for(int i=0;i<list.size();i++){//声明一个变量代表下标
            System.out.println(list.get(i));
        }
        //增强for循环:
        for(String str:list){
            System.out.println(str);
        }
        //迭代器遍历:
        Iterator it= list.iterator();
        while(it.hasNext()){![请添加图片描述](https://img-blog.csdnimg.cn/31f8553fe59f4492b999823393c00c85.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6L-36YCU44G9,size_20,color_FFFFFF,t_70,g_se,x_16)

            System.out.println(it.next());
        }
        //Lambda表达式遍历:
        list.forEach((obj)->{
            System.out.println(obj);
        });
    }
}

集合接口:

Collection接口:

  • 方法:

    1. int size():获取集合的长度.
    2. boolean isEmpty():判断集合是否为空
    3. boolean add(E element):给集合添加元素。
    4. boolean remove(Object o):删除指定元素
    5. Iterator iterator():返回在集合元素上进行迭代的迭代器
    6. void clear():清空集合
List集合:
  • 特点:

    • 有序的集合(有序体现在有下标进行标记,下标从0开始)

    • 可以包含重复的数据.

  • 常用方法:

    1. E get(int index):根据我们的下标获取指定元素。
    2. E remove(int index):移除指定下标的集合。
  • 其他:

    • <泛型>:指定集合存放的数据类型. 只能是类型不能是基本数据类型,即基本数据类对应的类

    • (简答题)泛型集合和非泛型集合有什么区别?

      一个是弱类型,一个是强类型。而弱类型是指无法在应用程序编译期间得到检查,如array对象,你可以往这个对象中添加数字和字符都没有问题。但是在遍历操作的时候可能会牵扯到数据类型的转换,在不同类型转换的时候可能会出现类型转换是的异常。而强类型则在编译期间进行检查,如list标明我们只能够在集合中存储string字符串类型,一旦添加其他类型的数据就会在编译期间出现错的提示。

      非泛型合集属于弱类型集合而泛型集合属于强类型集合。

  • 使用:

    public class TestList {
        public static void main(String[] args) {
            //创建list集合对象:
            List<String> list=new ArrayList<>();
            //往集合中存放数据:
            //size():获取集合的长度.
            int length= list.size();
            System.out.println("集合长度是:"+length);
            //boolean isEmpty():判断集合是否为空
            boolean bo=list.isEmpty();
            System.out.println("集合是否为空:"+bo);
            //boolean add(E element):给集合添加元素。
            boolean bo1=list.add("张三");//0
            list.add("张三");//1
            list.add("张三2");//2
            list.add("张三3");//3
            list.add("张三4");//4
            list.add("张三5");
            System.out.println("添加元素:"+bo1);
            System.out.println("集合长度是:"+list.size());
            //集合的遍历:
            //for循环遍历:
            System.out.println("---for循环遍历---");
            for(int i=0;i<list.size();i++){//声明一个变量代表下标
                System.out.println(list.get(i));
            }
            //增强for循环:
            //声明一个和变量同类型的变量进行存放集合中的数据
            for(String str:list){
                System.out.println(str);
            }
            //迭代器遍历:
            Iterator it= list.iterator();
            while(it.hasNext()){
                System.out.println(it.next());
            }
            //Lambda表达式遍历:
            list.forEach((obj)->{
                System.out.println(obj);
            });
        }
    }
    
Set集合
  • 特点

    • set集合不可以存放重复元素
    • set集合都是没有顺序的集合
    • 全部都是从collection继承过来的方法
  • 方法

    1. int size():获取集合的长度.
    2. boolean isEmpty():判断集合是否为空
    3. boolean add(E element):给集合添加元素
    4. boolean remove(Object o):删除指定元素
    5. Iterator<E> iterator():返回在集合元素上进行迭代的迭代器
    6. void clear():清空集合。
    
  • 使用

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class SetTest {
        public static void main(String[] args) {
            //创建一个set集合的对象
            Set<Integer> set = new HashSet<>();
            //集合添加数据
            System.out.println("添加数据1"+set.add(1));
            System.out.println("添加数据2"+set.add(2));
            System.out.println("添加数据3"+set.add(3));
            System.out.println("添加数据1"+set.add(1));
    
            //int size()获取集合的长度
            System.out.println("集合的长度是:"+set.size());//3
            //boolean isEmpty()集合是否为空
            System.out.println("集合是否为空:"+set.isEmpty());
    
            //集合的遍历
            //for (集合的泛型 变量名:集合名){}
            for (Integer i:set){
                System.out.println(i);
            }
            System.out.println("-------------------迭代器变量-----------------");
            //通过指针获取数据
            Iterator<Integer> iterator = set.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
            System.out.println("--------------------Lambda表达式遍历-------------------------");
            //obj代表集合中的每一个元素
            set.forEach((obj)->{
                System.out.println(obj);
            });
        }
    
    }
    
  • 案例

    获取重复的字符

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class Test1 {
        public static void main(String[] args) {
            Scanner sc=new Scanner(System.in);
            System.out.println("请输入一句话");//你好,我是张三
            
            //接受键盘输入
            String str=sc.nextLine();
            
            //把String类型的字符串,拆分成字符数组
            char [] chars=str.toCharArray();//{你,好,......}
            
            //创建Set集合
            Set<Character> characterSet=new HashSet<>();
            
            //for循环遍历
            for (char ch:chars){
                if(!characterSet.add(ch)){
                    System.out.println(ch+"是重复出现的字母");
                }
            }
            
        }
    }
    

Map集合

  • 特点

    • 是一个双类集合
    • 是一个包含键值对的集合
    • 是一个无序的集合
    • 键是不可以重复的,值是可以重复的
  • 方法

    1. V put(K key,V value) 将指定的值与映射中的指定键进行关联
    2. Set keySet
    3. V put(K key , V value):将指定的值与映射中的指定键进行关联
    4. int size() 返回此映射中键值映射关系的数量
    5. V get(Object key) 返回指定键所对应的映射值
  • 使用

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class MapTest {
        public static void main(String[] args) {
            Map<Integer,String> map = new HashMap<>();
            map.put(1,"张三");
            map.put(2,"李四");
            map.put(3,"王五");
            map.put(1,"田七");
            //获取键值对的映射个数
            System.out.println("集合的长度是:"+map.size());
            System.out.println(1+"对应的值是:"+map.get(1));
            System.out.println("集合是否为空:"+map.isEmpty());
    
            // 将map的key都放到set集合中
            // 将map集合转换成了set集合
            Set<Integer> set = map.keySet();
            // map集合的遍历 和set的遍历种类一样
            for (Integer i:set){
                System.out.println(i+"对应的值是:"+map.get(i));
            }
            map.forEach((key,val)->{
                System.out.println(key+"对应的值是"+val);
            });
            
        }
    }
    
  • 案例:

    键盘输入一句话,统计每一个字符出现得次数

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    //键盘输入一句话,统计每一个字符出现得次数。
    public class Test {
        public static void main(String[] args) {
            //键盘输入一句话,统计每一个字符出现得次数。
            Scanner sc=new Scanner(System.in);
            System.out.println("请输入一句话:");//asdasdasd
            String str=sc.nextLine();
            //{a,s,d,a,s,d,a,s,d}
            char [] chars=str.toCharArray();
            //创建一个Map集合:
            Map<Character,Integer> map=new HashMap<>();
            Set<Character> set=new HashSet<>();
            //遍历char数组:
            for(char ch:chars){
                //判断字符是否第一次出现
                if(set.add(ch)){//这是第一次出现
                    map.put(ch,1);
                }else{//不是第一次出现
                    int num= map.get(ch);
                    map.put(ch,num+1);
                }
            }
            //直接使用Lambda表达式遍历结合
            map.forEach((key,value)->{
                System.out.println(key+"出现了"+value+"次;");
            });
        }
    }
    

Collections 工具类

排序:

package collection;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;


public class Test {
    public static void main(String[] args) {
//        创建一个lsit集合
        Integer [] arr = {13,21,2,35,25,66};
//        数组转换为集合
        List<Integer> list = Arrays.asList(arr);
        Collections.sort(list);
//        随机排序
//        Collection.shuffle(list);
//        反转
//        Collections.reverse(list);
//        二分查找法
        int a;
        a = Collections.binarySearch(list,25);
//        查找极值
        int max = Collections.max(list);
        int min = Collections.min(list);
//        集合遍历

//        lambda表达式方法
        list.forEach((obj)->{
            System.out.print("-----"+obj);
        });
        System.out.println("\n-----------------------------------------------");
        System.out.println("25的下标为"+a);
        System.out.println("集合中的最大值"+max+",集合中的最小值"+min);
    }
}

package collection;

import java.util.*;

public class Student {
    private String name;
    private String clazz;
    private double score;

    public Student(){}
    public Student(String name,String clazz,double score){
        this.name = name;
        this.clazz = clazz;
        this.score = score;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public String getClazz() {
        return clazz;
    }

    public double getScore() {
        return score;
    }

    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }

//    重写toString方法,在打印该对象时显示的格式
//    默认是一个该文件的路径加一个16进制的hashCode值

//    @Override
//    public String toString() {
//        return "Student{" +
//                "name='" + name + '\'' +
//                ", clazz='" + clazz + '\'' +
//                ", score=" + score +
//                '}';
//    }

//    public static void main(String[] args) {
//        Student student = new Student("张三","一班",23);
//        System.out.println(student);
//    }
}

class TestList{
    public static void main(String[] args) {
//        创建一个学生对象
        Student student = new Student("张三","2班",23);
        Student student1 = new Student("张2","1班",83);
        Student student2 = new Student("张4","4班",63);
        Student student3 = new Student("张5","1班",63);
        Student student4 = new Student("张6","3班",73);
        Student student5 = new Student("张7","2班",79);
        Student student6 = new Student("张8","3班",71);

        Student []students = {student,student1,student2,student3,student4,student5,student6};
//      数组转换为集合
        List<Student> list = Arrays.asList(students);
//      创建两个map结合,一个存放总分,一个存放人数
        Map<String,Double> map = new HashMap<>();
        Map<String,Integer> map2 = new HashMap<>();
//        创建一个set集合用于分班
        Set<String> set = new HashSet<>();
//        对list集合进行遍历
        list.forEach((stu)->{
//           对学生进行分班
            if (set.add(stu.getClazz())){//这个学生是这个版的第一个人
                map.put(stu.getClazz(),stu.getScore());
                map2.put(stu.getClazz(),1);
            }else {
//                这个班级已有其他人,获取本班的原有的总成绩
                double sum = map.get(stu.getClazz());
                int count = map2.get(stu.getClazz());
                map.put(stu.getClazz(),sum+stu.getScore());
                map2.put(stu.getClazz(),++count);

            }
        });

//        遍历map集合
        map.forEach((key,val)->{
            System.out.println(key+"班级的总分为"+val);
        });
        map2.forEach((key,val)->{
            System.out.println(key+"班级的总人数为"+val);
        });

//        技术平均成绩
        set.forEach((obj)->{
            double sum = map.get(obj);
            int count = map2.get(obj);
            System.out.println(obj+"的平均分为"+sum/count);
        });
    }
}

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值