java面向对象5

JVM内存分配: 方法区, 栈, 堆,常量池

WS4H{_T7O3RQ%XI9OOG%KLW

怎么得到一个对象

DG}LLY(2H@4PJ)OPLJ7H4~N

1.拉姆达表达式

Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,
直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。
Java 8 引入的 Lambda 表达式的主要作用就是简化部分匿名内部类的写法。
能够使用 Lambda 表达式的一个重要依据是必须有相应的函数接口。所谓函数接口,是指内部有且仅有
一个抽象方法的接口。
Lambda 表达式的另一个依据是类型推断机制。在上下文信息足够的情况下,编译器可以推断出参数表
的类型,而不需要显式指名。

2.1 函数式接口

@FunctionalInterface , 函数式接口 : 接口内部,必须的只有一个抽象方法。
在接口中可以使用default修饰方法,那么该方法必须有方法体。

// annotation : 注解
@FunctionalInterface // 函数式接口 : 接口内部必须只有一个抽象方法
public interface AInterface {
   public abstract int sum(int x, int y);
}

//@FunctionalInterface : 好处在于写错可以有提示
interface BInterface{
   // 判断年龄是否大于18
   boolean isBigPeople(int age);  // 保证接口里只有一个方法,就是一个函数式接口
}
@FunctionalInterface
interface CInterface{
   // 输出一句话: name + "," + word
   void sayHi(String name, String word);
}

@FunctionalInterface
interface DInterface{
   // 产生一个随机整数
   int randomInt();
   //java1.8开始,接口中,可以使用default修饰方法,写方法的实现
   //default 修饰的方法,必须有方法体
   default int randomInt(int bound){
      Random random = new Random();
      int data = random.nextInt();
      return data;
   }
}

interface EInterface{
   // 产生一个随机整数
   int randomInt();
   int randomInt(int bound);   
}

/*
@FunctionalInterface  : 只能修饰interface
abstract class B{
   public abstract int add(int x);
}
*/

2.2 拉姆达表达式的使用

先了解一定的语法规则,后期在使用的时候,在逐渐熟悉更多的使用方式。

class F{
   //通过调用AInterface中的sum方法,求两个数的和
   int k(AInterface a ,int x, int y){
      return a.sum(x, y);
   }

   boolean b (BInterface b, int age){
      return b.isBigPeople(age);
   }

   void c(BInterface b, DInterface d){
      int r = d.randomInt();
      System.out.println("年龄:"+r);
      boolean b1 = b.isBigPeople(r);
      if(b1){
         System.out.println("成年人");
      }else{
         System.out.println("未成年");
      }
   }
}
import java.util.Random;

public class TestLambda {
   public static void main(String[] args) {
      //lambda表达式的使用 , 对应的接口要符合函数式接口的特征
      //函数的参数格式,(可以省略函数名字,可以省略参数类型), -> {函数体}
      //如果是无参的函数,那么就直接写()
      //如果是有参的函数,就写(参数名)
       AInterface aInterface = (a,b) -> {
          //内部把a , b 当接口中方法定义的类型使用
          /*if(a){  -- a 是int类型,参数接口中的类型使用
             return 0;
          }*/
          return a + b;
       };
       aInterface.sum(4,5);

       BInterface bInterface = (h) -> {
          return h >= 18;
       };
       bInterface.isBigPeople(19);

       CInterface cInterface = (name, word) -> {
          System.out.println(name+","+word);
       };
       cInterface.sayHi("alice","欢迎光临");

       /*DInterface dInterface = () -> {
          return (int) (Math.random()*100);
       };*/
      DInterface dInterface = () -> {
         Random random = new Random();
         return random.nextInt();
      };
      System.out.println(dInterface.randomInt());

      //计算两个数的和,输出和
      int he = ((AInterface)(x,y) -> {return x + y;}).sum(3,5);
      System.out.println("he:"+he);

      // *** 方法调用的时候: 参数的类型,参数的个数,参数的返回值
      //*** 方法的定义: 方法签名(方法的修饰符,返回值,方法,参数)

      //调用F中的k方法
      F f= new F();
      int he1 = f.k((a,b) -> {return a + b;}, 4,5);

      //调用F中的b方法
      System.out.println("he1:"+he1);
      boolean b1 = f.b((m)->{return m >= 18;}, 20);

      // 调用F中的c方法
      f.c((n)->{return n >= 18;}, ()->{
         return (int) (Math.random() * 100 + 1);});
   }
}

image-20230731194747212

2.== 和 equals的区别

  • == , 基本数据类型,判断数据值是否相等

  • == , 引用类型,判断引用类指向的地址是否相等,即是否为同一个对象。

  • equals是父类Object中提供的的一个equals方法,用于制定两个对象是否相等的比较规则。

    Object中的equals默认是比较两个对象的地址是否相同。

  • 子类重写父类的equals方法,自定义比较规则:

    比如: 判断两个点是否相同,可以判断两个点的x位置和y位置同时相等,则两个点相同。

  • 如果两个对象比较equals为true ,那么这依然不能说明是否为同一个对象。

3.Object类型:所有类的父类。

image-20230731194418311

import java.lang.Object;    // 省略了
// 一般省略: extends Object
// Object 是所有类的父类:该类中封装了常用的属性和方法
public class Point extends Object{
   int x;
   int y;
   public Point(){
      super();  // 省略
   }
   public void up(){
      y++;
   }
}

class TestPoint{
   public static void main(String[] args) {
      Class pointClass = Point.class;
      Point p = new Point();
      Class pClass = p.getClass();
      //可以重写toString
      //*** toString: 显示成员变量的值
      String str = p.toString();   // 继承的toString
      System.out.println(str);   //day5.Point@3ac3fd8b
      //*** 输出语句,输出某个引用的时候,本质上是调用toString方法。
      System.out.println(p);  //day5.Point@3ac3fd8b

      //可以重写hashCode
      int code = p.hashCode();  // 继承了hashCode

      // 一般会重写euqals方法。
      // ** 自定义比较规则(一般比较属性值是否相同。)
      boolean b = p.equals(p); // 继承了父类的equals方法。
   }
}

Objects类型的使用:

import java.util.Objects;
public class TestOjects {
   public static void main(String[] args) {
      Shape s = new Shape();
      s.x = 5;
      s.y = 10;

      Shape s1 = new Shape();
      s1.x = 5;
      s1.y = 10;

      boolean flag = Objects.equals(s,s1);  // -- ··调用到Shape类型的equals方法。

      System.out.println("s -- > s1:"+flag);  // true

      Point p = new Point();
      p.x = 10; p.y = 10;
      Point p1 = new Point();
      p1.x = 10; p1.y = 10;
      boolean b = Objects.equals(p,p1);  // -- 调用到Point类型的equals方法

      System.out.println("p -- > p1:" + b);  // false(Point类型没有重写equals方法,使用Object中的equals方法。)
   }
}

4.重写equals方法

从Object类中基础的equals方法,不满足子类的使用的时候,可以重写该方法。
重写equals : equals的比较,一般是比较两个对象的成员变量的值是否相等。

public class Shape {
   int x;
   int y;
   public Shape() {}

   //public String toString(){ 
   // //return Shape.class + " (" + x + "," + y + ")";
   // return this.getClass() + "(" + x + "," + y + ")";
   //}

   @Override
   public String toString() {
      return "Shape{" +
            "x=" + x +
            ", y=" + y +
            '}';
   }

   // 重写equals:equals的比较,一般是比较两个对象的成员变量的值是否相等
   // 如果两个对象的x相等,那么euqals结果为true,否则为false
   public boolean equals(Object o){  // 向上造型
      //如果是null,说明不等
      if(o == null){
         return false;
      }
      //如果类型不同,说明不等
      if(this.getClass() != o.getClass()){
         return false;
      }
      //如果是自己,说明相等
      if(this == o){  // 判断的是引用地址是否相等,如果相等,说明是同一个对象
         return true;
      }
      //如果类型相同,不是自己,判断属性值是否相等
      if(o instanceof Shape){
         Shape shape = (Shape) o;  // 强制类型转换
         if(shape.x == this.x && shape.y == this.y){    // 比较规则
            return true;
         }
      }
      return  false; //不符合上面的条件,说明不相等
   }
}

class TestShape{
   public static void main(String[] args) {
      Shape s1 = new Shape();
      s1.x = 5;
      s1.y = 10;
      Shape s2 = new Shape();
      s2.x = 5;
      s2.y = 10;
      System.out.println("toString");
      System.out.println(s1);
      System.out.println(s2);
      System.out.println("==");
      System.out.println(s1 == s1);  // true
      System.out.println(s1 == s2);  // false
      System.out.println("equals");
      System.out.println(s1.equals(s1));  // ture
      System.out.println(s1.equals(s2));  // true
      System.out.println("==========================================");
      String a1 = "a";
      String a2 = "abc";
      String a3 = new String("a");
      String a4 = new String("abc");
      String a5 = "abc";
      System.out.println(a1 == a2); // false 不同对象
      System.out.println(a1 == a3); // false 不同对象
      System.out.println(a2 == a3); // false 不同对象
      System.out.println(a2 == a4); // false 不同对象
      System.out.println(a2 == a5); // true  相同对象(字符串常量池规则)
      System.out.println(a2.equals(a3)); // false  数据值不同
      System.out.println(a2.equals(a4)); // true   数据值相同  重写后的equals方法比较数据值

   }
}

5.静态代码块

类中的代码块可以使用static修饰,则被称为静态代码块

public class StaticBlockDemo {
   public static void main(String[] args) {
      //** 静态代码块,优先于静态方法的调用
      //*** 如果有什么代码,需要在类加载的时候,就执行,把这个代码放在静态代码块中(静态代码块只执行一次。)。
      Foo.show();  //  -- 通过类名 ,直接调用静态方法

      //** 静态代码块,优先于构造函数执行
      //*** 如果有代码,希望在创建对象之前(构造函数调用之前),都要执行,可以使用非静态代码块(非静态代码块执行多次)。
      Foo f = new Foo();
      f.print();
      //Foo f1 = new Foo();
   }
}
// 加载顺序: 静态代码块 -> 静态方法 -> 非静态代码块 -> 构造器函数 -> 非静态方法
class Foo{
   public Foo(){
      System.out.println("构造器函数");
   }
   static {
      System.out.println("这个是静态代码块");
   }
   { //经过编译,这个内容,就放在了构造函数内部代码之前了
      System.out.println("这个是非静态代码块");
   }
   public void print(){
      System.out.println("这个是普通方法");
   }
   public static void show(){
      System.out.println("这个是静态方法"); // 静态的东西不属于对象,而属于类
   }
}

image-20230731195524093

6.面向对象特征——封装

import java.util.Objects;
public class Student {
   private int age;
   private String hobby;
   private String name;
   private String sex;
   //自动生成get/set方法
   //** set :给成员变量赋值,set方法有参数,无返回值
   //** get :获取成员变量的值,get值方法无参数,有返回值
   //** 方法名的特征: get属性名首字母大写,set属性名首字母大写

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }

   public String getHobby() {
      return hobby;
   }

   public void setHobby(String hobby) {
      this.hobby = hobby;
   }

   public String getName() {
      return name;
   }

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

   public String getSex() {
      return sex;
   }

   public void setSex(String sex) {
      this.sex = sex;
   }

   @Override
   public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      Student student = (Student) o;
      return age == student.age
            && Objects.equals(hobby, student.hobby)  // Objects.equals(引用1, 引用2) -- 工具方法,判断是否相等。
            && Objects.equals(name, student.name)
            && Objects.equals(sex, student.sex);
   }

   @Override
   public int hashCode() {
      return Objects.hash(age, hobby, name, sex);  // Objects.hash -- 工具方法,计算要给hash值。
   }
}

class TestStudent{
   public static void main(String[] args) {
      Student stu = new Student();
      stu.setAge(20);
      stu.setHobby("看书");
      stu.setName("tom");
      stu.setSex("男生");
      System.out.println("-----------获取成员变量值-----------");
      System.out.println(stu.getName() + ", " + stu.getSex() + "," + stu.getHobby() + " ," + stu.getAge());
   }
}

7.面向对象三大特性—继承

  • A类通过extends关键字,继承B类,Java是中是单继承,一个子类只能有一个父类,一个父类可以

    有多个子类

  • 继承能够提高代码的重用性

8.面向对象三大特性—多态

  • 对象是多种状态的。

  • 父类的引用指向子类的对象

    Father s=new Son();

//打印机类(父类)
public class Printer {
   public void print(){

   }
}
//三个打印机类的子类
class Printer3D extends Printer{
   public void print(){// 父类方法的重写
      System.out.println("3D打印机正在打印");
   }
}
class PrinterBlack extends Printer{
   public void print(){
      System.out.println("黑白打印机正在打印");
   }
}
class PrinterColor extends Printer{
   public void print(){
      System.out.println("彩色打印机正在打印");
   }
}
  • 父类的引用指向子类的对象

    Father s=new Son();

//打印机类(父类)
public class Printer {
   public void print(){

   }
}
//三个打印机类的子类
class Printer3D extends Printer{
   public void print(){// 父类方法的重写
      System.out.println("3D打印机正在打印");
   }
}
class PrinterBlack extends Printer{
   public void print(){
      System.out.println("黑白打印机正在打印");
   }
}
class PrinterColor extends Printer{
   public void print(){
      System.out.println("彩色打印机正在打印");
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值