Java第三周 面向对象相关

本文详细介绍了Java中的面向对象特性,包括构造方法的定义与细节,如构造方法的重载、默认构造器的使用。接着讨论了`static`关键字的作用,代码块的类型及其执行顺序,以及继承的概念、特点与注意事项。文章还涉及了多态的原理、优势和应用场景,并探讨了抽象类与接口的区别。最后提到了方法参数和返回值与类、接口的关系,以及内部类和匿名内部类的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

构造方法

构造方法的定义:

1)方法和类名一致
2)没有具体的返回值,也不带void。

构造方法支持方法重载(重载要求,方法名相同,参数列表不同,与返回值无关)
格式:public 方法名和类名一致(要么空参/要么带上形式参数列表){}

// 无参构造器
class Student {
 public Studen (){
 	System.out.println("这是Student的无参构造方法");
 }
  //有参构造方法:带上参数类型以及参数名
    public Student(String name){
        System.out.println(name);
        System.out.println("这是带一个参数的有参构造方法");
    }

 public Student(String name,int age){
        System.out.println(name+"---"+age);
        System.out.println("这是带两个参数的有参构造方法");
    }
}

构造方法的细节:

  1. 如果一个类中没有声明构造方法,系统会默认提供一个无参的构造方法
    2)如果一个类中提供了有参构造器,系统不会再提供默认的无参构造器,如果此时再使用无参构造器创建对象,那就就会报错。
class Student {
    private String name;
    private int age ;

//有参的构造器
    public Student (String name,int age){
            this.name = name;
            this.age = age;
    }

}
public class StudentDemo{
    public static void main(String[] args) {
    	//使用无参构造器创建对象
        Student student = new Student();
        //此处会报错,没有无参构造器
    }
}

通过构造器给成员变量赋值的方式:
1)无参构造器只能通过,setXxx(xx)进行赋值;
2)有参构造器可以直接进行赋值;

//定义一个手机类
class Phone{
    //品牌
    private String brand ;
    //价格
    private int price ;
   /* //无参构造方法
    public Phone(){}


    //只是提供了有参构造方法
 public Phone(String brand,int price){//局部变量,要给成员变量赋值
        this.brand = brand ; //赋值
        this.price = price ;
    }*/


//idea:快捷键  alt+ins---->Constructor--->select none:生成无参构造方法


    public Phone() {
    }




    //idea:快捷键  alt+ins---->Constructor---> ctrl+a-->生成有参构造方法,给所有的成员变量赋值


    public Phone(String brand, int price) {//"Iphone13",4999
        this.brand = brand;
        this.price = price;
    }
    //对外提供公共的方法访问setXXX(xx)/getXXX()
    public String getBrand() {
        return brand;
    }
   public void setBrand(String brand) {
        this.brand = brand;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
}


//测试类
public class ConstructorDemo2 {
    public static void main(String[] args) {


    //方式1:使用默认的无参构造方法创建类对象,通过setXXX()赋值
        Phone p = new Phone() ;  //只提供了有参构造
     //方法,没有提供无参,系统不会在提供了,所以报错! 永远给出无参
        p.setBrand("华为p40") ;
        p.setPrice(6799);
  System.out.println(p.getBrand()+"---"+p.getPrice());
System.out.println("-----------------------------------------") ;
        //方式2:使用有参构造方法创建当前类对象,直接赋值
        //,通过getXXX()获取值即可
        Phone p2 = new Phone("Iphone13",4999) ;
        System.out.println(p2.getBrand()+"---"+p2.getPrice());
    }
}

一个标准类 :
成员变量:属性私有化
成员方法:setXXX(xx)/ getXXX()
构造方法: 无参构造方法永远给出来的!
有参构造方法(开发中,视情况而定
成员变量:
变量的定义的时候:如果能够描述这个事物的属性—定义成员变量

static 关键字

特点:
1)随着类的加载而加载,
类在在加载的时候,静态相关的成员(类成员:静态的变量或者静态的方法),随着类的加载而先进内存(静态区)

2)优先于对象存在, 不能和this共存

3)static能体现"共享,共用"的意思
如果需求中有"共用"含义,这个变量直接使用static修饰

4)被static修饰的成员(变量/方法),推荐的访问方式是使用类名.静态变量
类名.静态方法名()

当然可以使用类名 对象名 = new 类名() ;
对象名.静态变量() (不推荐)
对象名.静态方法() (不推荐)
在使用静态相关变量/方法的注意事项:
1)非静态的方法,既可以静态的,也可以访问非静态的(要么访问静态变量/静态的方法)
2) 简单记忆:
静态只能访问静态的东西(静态变量/调用静态方法)

class Demo{
    //非静态的成员变量
    public int num = 10 ;
    //静态的变量
    public static int num2 = 20 ;
    //非静态的成员方法
    public void function(){
        System.out.println("function Demo");
    }
    //私有的成员方法
    public static void method(){
        System.out.println("method Demo...");
    }
}
//测试类
public class StaticDemo {
    public static void main(String[] args) {
        //访问Demo类的成员变量
        Demo d = new Demo() ;
        System.out.println(d.num); //访问的非静态的成员变量
       // System.out.println(d.num2);//访问静态的成员变量 (使用对象名访问静态成员变量:不推荐)
        System.out.println(Demo.num2); // 使用类名来访问静态的成员变量
        System.out.println("--------------------------------------------");
        //访问非静态的成员方法
        d.function();
        //使用对象命名来访问静态的成员变量  (不推荐使用对象名来访问静态的方法)
       // d.method();
        //类名.静态方法名() ;
        Demo.method();  //回想 java.lang.Math工具类  ---->public static double random()
                        //Math.random():获取 [0.0,1.0)的随机数
    }
}

代码块

局部代码块:比较简单,在局部位置(方法定义中)定义的{},作用:限定某个变量的生命周期(很少见)
构造代码块:在类的成员位置 ,作用:
在执行构造方法之前,如果存在构造代码块,优先执行构造块,然后执行构造方法

可以将构造方法中共性内容,放在构造代码块中!(优先级:构造代码块>构造方法)

静态代码块 (实际开发中用的比较多:后期 二阶段:读取jdbc配置文件/加载某个框架的核心配置文件)

static{},在类的成员位置 ,类一加载,静态代码块先执行!

类就加载一次,静态代码块也就执行一次就完毕!

一个类中如果有静态代码块,有构造代码块,有构造方法

静态代码块 > 构造代码块 > 构造方法

//定义类
class Code{

    public static int num = 100 ;
    public int num2 = 20 ;

    //定义非静态的成员方法
    public void method(){
        System.out.println(num) ;
        System.out.println(num2);
    }
    public static  void function(){
        System.out.println("function Demo2");
    }
    //定义静态成员方法
    public static void show(){
       // System.out.println(num2) ;//静态只能访问静态的
        System.out.println(num) ;//静态变量
        System.out.println("--------------------") ;
       // method() ;//非静态的方法在这里不能调用
        function() ;
    }

}
//测试类
public class StaticDemo2 {
    public static void main(String[] args) {
            //访问Code类里面的method方法
            Code code = new Code() ;
            code.method();
            //调用show方法:类名来访问
            Code.show();
          //  boolean flag = compare(10,20) ;
    }
    //定义静态方法:比较两个是否相等(int类型)
    public static boolean compare(int a,int b){
        return  a==b;
    }
}

继承性

定义:将多个事物(类)的共性内容抽取到一个独立的事物(类)中,
这个事物(类)和其他事物(其他类)之前产生一种关系,称为"继承" 关键字 “extends”
格式:
class 父类名{
共性内容:属性私有化
对外提供公共的访问方法
//其他成员方法
}
class 子类名 extends 父类名{

}
继承的特点:
1)提高了代码的复用性
2)提高了代码的维护性(方便后期维护)
3)类与类产生的继承关系,是多态的前提条件!
弊端:
继承的关系:是存在局限性,不要为了使用部分功能而去使用继承!
继承的好处:
1)类和类之间的关系,只支持"单继承"

class Fu{}
class GrandFu{}
class Zi extends Fu,GrandFu{}//错误的!  (多继承,Java没有多继承的概念)

2)不支持多继承,但是可以 “多层继承”

class GrandFather {
    public void function(){
        System.out.println("我是爷爷...");
    }
}
//父类1
class Father extends  GrandFather{
    public void show(){
        System.out.println("我是老子...");
    }
}
//父类2
/*class Mother{
}*/
//子类
//class Son extends  Father,Mother{//类和类之间,只能单继承!
//}
//子类
class Son extends  Father{
    //特有功能
    public void playGame(){
        System.out.println("会玩游戏");
    }
}

//测试类
public class ExtendsDemo2 {
    public static void main(String[] args) {
        //直接最具体的类Son
        Son s = new Son() ;
        s.function(); //Father类继承自GrandFather 继承过来的
        s.show(); //Father类的的show方法
        s.playGame();//自己的功能
    }
}

继承中的注意事项:
1)子类继承父类,只能继承父类的非私有的成员,私有的成员,可以间接的访问
2) 子类继承父类,构造方法是不能继承的,只能间接访问! 如何访问—就是通过一个"super"来访问

class Fu{
   //父类的私有成员变量
    private  int number =10 ;
    //非私有的成员变量
    public int num2 = 20 ;
    public void show(){
        //访问number
        System.out.println(number);
        System.out.println("show Fu");
    }
    //私有的成员方法
    private void method(){
        System.out.println("method Fu");
    }
    public void showMsg(){
        method(); //在公共方法中,间接访问了父类 私有成员方法
    }
}
//子类
class Zi extends  Fu{


    public void function(){
        System.out.println("function Zi");
    }
}
//测试类
public class ExtendsDemo {
    public static void main(String[] args) {
        //创建子类对象
        Zi zi = new Zi() ;
        //System.out.println(zi.number); //父类的number成员变量 已经被私有访问了
        zi.show() ;
        //zi.method() ;//method()' has private access
        zi.showMsg() ;
    }
}

继承中关于成员变量的问题
1)如果子类继承父类,子类的成员变量名称和父类的成员变量不一致,分别访问即可(比较简单一些)
2)如果子类中的成员变量名称和父类的成员变量一致,如何访问呢?
就近原则机制
1)首先先在子类的局部位置(成员方法)找,如果有,就使用
2)如果子类的局部位置没有,那么就在子类的成员位置中找,有就使用
3)如果子类的成员位置也没有,那么就在父类的成员位置中找,有就使用,
4)如果父类也没有,继续往他的父类上找,最终顶层父类中都没有,那么报错(找不到这个变量!)

//父类
class Father {
    public int num1 = 10 ;
    public int number = 100 ;
}
//子类
class Son extends  Father{
    public int num2 = 20 ;
    public int number = 200 ;
    //成员方法
    public void show(){
        //局部变量
       // int number = 300 ;
        //System.out.println(num1) ;//10
        //System.out.println(num2) ;//20
        System.out.println(number);
    }
}
//测试类
public class ExtendsDemo2 {
    public static void main(String[] args) {
       //创建子类对象
        Son s = new Son() ;
        s.show();
    }
}

继承中构造方法的目的
构造方法目的:就是类的成员进行数据初始化!

继承关系中,子类不能继承父类的构造方法,但是可以间接通过super()来访问,为什么子类中构造方法默认是这种机制呢?

子类的所有构造方法都默认访问父类的无参构造方法(子类的所有构造方法的第一句话super();,可以省
略不写), 因为:jvm 校验语法的时候, class Zi extends Fu{}

存在继承关系,需要让父类先初始化,因为子类可能会用父类的数据,所以采用"分层初始化!"
面试题:继承关系中, 父类之中如果没有无参构造方法(存在有参构造方法),子类会出现什么情况?如何解决呢?
子类全部报错,子类的所有构造方法都默认访问父类的无参构造方法(子类的所有构造方法的第一句话super();,可以省略不写)
1)解决方案1:永远给出类的无参构造方法

2)如果现在不给出父类无参构造方法,如何解决呢?
让子类的所有构造方法显示的访问父类的有参构造方法!(只要父类出现初始化 :执行构造方法就是初始化)

3)子类的所有构造方法中的某一个只要能够让父类初始化即可!

创建Zi zi = new Zi() ; 在执行Zi类的无参构造方法的时候
让它先执行子类的有参构造方法 this(xx) ;
然后在子的有参构造方法中,让它先让父类初始化 super(xx) ; 访问父类的有参构造方法

//父类
class Fu{
   /* public Fu(){
        System.out.println("Fu无参构造方法");
    }*/
    public Fu(String name){
        System.out.println("Fu的有参构造方法--->"+name);
    }
}
//子类
class Zi extends  Fu{
    //zi的无参构造方法
    public Zi(){
       //    super() ; //隐藏的(默认的)
       //super("随便给") ;
         this(100) ;  //this(xx) :访问就是本类中有参构造方法
        System.out.println("zi的无参构造方法");
    }
    public Zi(int num){
       // super();
       // this() ;
        super("随便给") ;
        System.out.println("Zi的有参构造方法"+num);
    }
}
//测试类
public class ExtendsDemo3 {
    public static void main(String[] args) {
        //创建子类对象
        Zi zi = new Zi() ;
        //System.out.println("----------------------------------") ;
        //Zi zi2 =  new Zi(10) ;
    }
}

多态

多态的概念:
从现实世界事物中考虑 :“多态” 一个事物多种形态!

Java面向对象中(程序中)“多态”: 一个类体现出内存的变化

多态:能够体现事物的不同形态(程序中,内存的变化!)

多态的前提条件:
1)必须有继承关系 (如果没有继承,不谈多态)
2)必须存在方法重写
3) 必须存在父类引用指向子类对象
格式:
父类名 对象名 = new 子类名() ; (向上转型!)
父类名 对象名 = new 子类名() ;

多态的成员访问特点:
1)成员变量:编译看左,运行看左!
2)成员方法:编译看左,运行看右 !(非静态的成员方法)
静态的方法:算不上方法重写,这种 跟类相关,类一加载就可以直接使用(类名.方法名())
3)构造方法:由于存在继承,构造方法在执行的时候,分层初始化,先让父类初始化,然后再是子类进行构造初始化!

//动物类
class Animal{
    int age = 5 ;


    //成员方法
    public void eat(){
        System.out.println("动物都需要吃饭");
    }


    public static void method(){
        System.out.println("method Animal");
    }


    public Animal(){
        System.out.println("这是Animal类的无参构造方法");
    }
}
//狗类
class Dog extends  Animal{
    int age = 3 ;
    public Dog(){
        System.out.println("这是Dog类的无参构造方法");
    }
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
    public static void method(){
        System.out.println("method Dog");
    }
}
//猫类
class Cat extends  Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
//测试类
public class DuoTaiDemo {
    public static void main(String[] args) {
        //必须存在父类引用指向子类对象
        //    格式:
        //父类名  对象名  = new  子类名() ;
        Animal a = new Dog(); //多态的写法
        System.out.println(a.age);
        //System.out.println(a.number); //Animal类中不存在number变量,编译报错
        //访问成员方法
        a.eat() ;
      //  a.show() ; //Animal类中不存在这个方法
        //静态的方法:类名方法
        //a.method();
        Animal.method();
        Dog.method();


    }
}

多态的好处:
1)可以提高代码的扩展性 (父类引用指向子类对象 Fu fu = new Zi()) 多态保证的 (重点)
2)可以提高代码的复用性以及维护性(由继承保证的)

//父类 --动物类
class Animal{
    public void eat(){
        System.out.println("动物都需要吃饭");
    }
    public void sleep(){
        System.out.println("动物都需要睡觉");
    }
}
//子类
//狗类
class Dog extends  Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
    @Override
    public void sleep() {
        System.out.println("狗趴着睡");
    }
    //特有功能
    public void lookDoor(){
        System.out.println("狗看门");
    }
}
//猫类
class Cat extends  Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    @Override
    public void sleep() {
        System.out.println("猫躺着睡");
    }
}
//猪类
class Pig extends Animal{
    @Override
    public void eat() {
        System.out.println("猪拱白菜");
    }
  @Override
    public void sleep() {
        System.out.println("猪斜着睡");
    }
}
//定义一个动物工具类
class AnimalTool{


    //构造方法私有化
    private AnimalTool(){}


    //对外提供公共的访问
    /*public static void useCat(Cat c){//方法的形式参数引用类型:类---调用方法,需要传递当前类对象
        c.eat();
        c.sleep();
    }
    //养一只狗
    public static void useDog(Dog d){
        d.eat();
        d.sleep();
    }


    //提供使用猪的方法
    public static void usePig(Pig p){
        p.eat();
        p.sleep();
    }*/


    public static void useAnimal(Animal a){
                            //形式参数是一个引用类型 Animal a = new Cat()/new Dog()/new Pig()
        a.eat();
        a.sleep();
    }
}
//测试类
public class DuoTaiDemo {
    public static void main(String[] args) {
        //养一只狗
        Dog d = new Dog() ;
        d.eat();
        d.sleep();
        Cat c = new Cat();
        c.eat();
        c.sleep();
        System.out.println("-------------------------");
        //优化上面代码:在测试类中提供一些静态的方法
        /*useCat(c);
        useDog(d);
        Pig p = new Pig() ;
        usePig(p);
        usePig(new Pig()); //匿名对象
        System.out.println("------------------------------------------"); */
        //虽然将每一个类型都作为形式参数传递, 随着类型的增加,方法会越来越多
       // AnimalTool.useCat(new Cat()); //要么直接创建新的猫对象 Cat cc = new Cat();
       // AnimalTool.useDog(new Dog());
       // AnimalTool.usePig(new Pig());


        //继续优化上面代码: 只是将上面的方法放在了类中,通过类名访问,但是代码量还是很大
        //多态:父类引用指向子类对象


        Animal a = new Cat() ; //猫是动物(堆内存创建的是猫)
        Animal a2 = new Dog() ;//堆内存现在狗对象
        Animal a3 = new Pig() ;//堆内存是猪
        AnimalTool.useAnimal(a);
        AnimalTool.useAnimal(a2);
        AnimalTool.useAnimal(a3);
        
        System.out.println("------------------------------------------");
        Animal a4 = new Dog() ;
        a4.eat();
        a4.eat();
       /* Dog dd = new Dog() ;
        dd.lookDoor();*/
        //a4.lookDoor() ;
    }
    //养一只猫
   /* public static void useCat(Cat c){//方法的形式参数引用类型:类---调用方法,需要传递当前类对象
        c.eat();
        c.sleep();
    }
    //养一只狗
    public static void useDog(Dog d){
        d.eat();
        d.sleep();
    }
    //提供使用猪的方法
    public static void usePig(Pig p){
        p.eat();
        p.sleep();
    }*/
}

多态的弊端:
父类引用指向子类对象, 父类名 对象名 = new 子类名() ;(向上转型)这种格式无法访问子类的特有功能
解决方案:
1)直接创建子类对象 子类名 对象名 = new 子类名() ;
虽然可以,但是new 子类名() ;需要开辟堆内存空间(消耗内存空间) (内存角度考虑不太好)
2) 推荐:向下转型
将父类引用强转为子类引用!-----就是我们 基础"强转类型转换" (将大类型—小类型)
int num = 65 ;
char c = (char)num ; // ‘A’
父类名 父类的引用 = new 子类名() ; 向上转型
Fu f = new Zi() ;
子类名 对象名 = (子类名)父类的引用; 向下转型 --前提必须有向上转型
Zi z = (Zi)f;

//父类
class Father{
    public void study(){
        System.out.println("Father会JavaEE...");
    }
}
//子类
class Son extends  Father{
    @Override
    public void study() {
        System.out.println("Son不仅会JavaEE,还会Python...");
    }


    //特有功能
    public void playGame(String gameName){
        System.out.println("son会玩"+gameName);
    }
}
//测试类
public class DuoTaiDemo2 {
    public static void main(String[] args) {
        //多态的形式测试:
        //父类引用指向子类对象
        Father f = new Son() ;
        //多态的中的成员访问特点:编译看左,运行看右
        f.study();
       // f.playGame("csgo") ;//  左边父类中没有方法


        // 1)直接创建子类对象  子类名 对象名 = new 子类名() ;
       // Son s = new Son() ;
      //  s.playGame("csgo");


        //2)子类名 对象名 = (子类名)父类的引用;  向下转型    --前提必须有向上转型
        Son s = (Son)f ;  //(推荐方式)
        s.playGame("csgo");
    }
}

super和this的区别
this:代表当前类对象的地址值引用
super:代表父类的空间标识(理解为:父类对象地址值引用)
this.变量名:访问的本类的成员变量
super.变量名:访问的父类的成员变量

class Test{
                 public static void main(String[] args){

                     Zi zi = new Zi();
                     zi.show() ;
             }
         }

        class Fu{
                 int num = 10;
         }
         class Zi extends Fu{
                 int num = 20 ;
                 public void show(){
                     int num = 30 ;
                    //补全代码
                     Sysetem.out.println(num) ;  //30   就近原则
                     Sysetem.out.println(this.num) ; //20
                     Sysetm.out.println(super.num) ;//10
              }
         }
/
class Fu2{
    int num = 10;
}
class Zi2 extends  Fu2{
    int num  = 20;
    public void show(){
        int num = 30 ;
        //补全代码
        System.out.println(num) ;
        System.out.println(this.num);
        System.out.println(super.num);
    }
}
public class ExtendsTest {
    public static void main(String[] args) {
            Zi2 zi  = new Zi2() ;
            zi.show();
    }
}

抽象类

一个事物的某个行为应该具体的事物的具体体现,讲这个事物顶层次(父类)可以定义“抽象”
举例
动物事物 — 都具备吃和睡的行为
只有见到具体的事物才具备的具体行为“猫”“狗”吃和睡不一样,应该在具体事物中给出具体的体系,那么在
动物事物中,仅仅一个声明!(没有方法体)
抽象类的定义:
abstract class 类名{}
有抽象方法的类一定是抽象类,抽象类不一定都是抽象方法(重点)

抽象方法的 格式
权限修饰符 abstract 返回值类型 方法名(空参/无参)
抽象类的特点:
1)抽象类不能实例化(不能创建对象)
2)抽象类的子类如果也是抽象类,不能实例化,一定会提供最具体的子类,完成实例化(创建对象)

抽象的父类名 对象名 = new 具体的子类名();抽象多态

//定义动物类
abstract  class Animal{ //抽象的动物类
    /*public void eat(){
        System.out.println("动物都需要吃饭");
    }*/
    int age = 5;


    public abstract  void eat() ; //抽象方法   (仅仅给出一个方法声明,没有方法体{})
    public abstract  void sleep() ;


    public void showAnimlMsg(){
        System.out.println("showAnimlMsg Animal");
    }
    public Animal(){
        System.out.println("Animal的无参构造方法");
    }
}
//狗类
class Dog extends Animal{
    public Dog(){
        System.out.println("dog的无参构造方法");
    }


    int age =3;
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }


    @Override
    public void sleep() {
        System.out.println("狗躺着睡");
    }
}


//测试类
public class AbstractDemo {
    public static void main(String[] args) {


        //创建动物类对象 类名 对象名 = new 类名();
        //Animal a = new Animal() ;//抽象类不能new


        //多态的格式
       // Animal a = new Dog() ; //如果子类是抽象类,子类下面没有子类(没有任何意义!)


        //抽象的父类名  对象名  = new  具体的子类名() ;  抽象类多态
        //Dog是具体类
        Animal a = new Dog();
        a.eat();  //编译看左,运行看右
        a.sleep();
        System.out.println(a.age) ; //编译看左,运行看左
    }
}

抽象类的成员特点:
成员变量:
既可以是变量,也可以是常量(加入final修饰)
成员方法:
皆可以存在抽象方法(不能省略abstract 关键字,必须强制子类重写),也可以定义非抽象方法 定义非抽象方法
构造方法
无参构造/有参构造都可以存在,构造方法都需要让父类先初始化,然后再是子类进行初始化

abstract class Person{ //抽象类的人类


    //定义一个成员变量
    public int number = 10 ;
    public static final int number2 = 20 ;


    //非抽象方法 ,不需要被子类重写
    public void show(){
        System.out.println(number);
        System.out.println(number2) ;
    }


    //抽象方法:强制子类必须重写
    public abstract void work() ;


    public Person(){
        System.out.println("Person()");
    }
    public Person(String str){
        System.out.println("Person(Str)"+str);
    }
}
//子类
class Worker extends  Person{
    public Worker(){
        System.out.println("Worker()");
    }
    public Worker(String str){
        super(str); //访问父类的有参构造
        System.out.println("Worker(Str)"+str);
    }


    //重写父类的抽象功能
    @Override
    public void work() {
        System.out.println("程序员不断的去学习新技术!");
    }
}
//测试类
public class AbstractDemo2 {
    public static void main(String[] args) {
        //抽象类多态
        Person p = new Worker() ;
        p.show() ;


        p.work() ;
        System.out.println("--------------------------------");
        Person p2 = new Worker("helloworld") ;
    }
}

面试题:
如果一个类没有任何抽象方法,把这个类定义为抽象类的意义?
意义就是:不让外界直接创建对象(抽象类不能创建对象)—需要提供具体的子类进行实例化!

abstract 和那些关键字冲突?
不能private一块用:被private修饰的成员需要在当前类进行访问,而如果加入abstract,强制子类完成…
不能和final一块用: 被final修饰的成员方法,不能被重写!而abstract抽象方法,必须强制子类重写
不能和static一块用:被static修饰的成员方法,算不上重写…
abstract关键字应用范围:
1)定义类—抽象类
2)定义方法—>抽象方法

接口

接口 体现的是这个事物 本身不具备的功能,额外的功能

中国人 —>经过后天学习“英语口语”—>具备说“英语口语”的行为

接口定义—java代码定义 关键字
interface 接口名{} 接口名标识符----> 和类名起名一致“大驼峰命名法”
接口的特点:
1)接口的方法不能有方法体,只能是抽象方法 而且隐藏 public abstract(可以省略不写)
2)接口不能实例化(不能创建对象)
3)如果接口的实现类他是一个抽象类(不能实例化),肯定有一个具体的接口的实现类来进行new对象
接口名 对象名 = new 具体的子实现类();接口多态
要实现接口里面的额外功能 --> 才具备这功能
开发中定义接口的实现类(子类)名
class 接口名 +lmpl implements(实现) 接口名 {
}

//有一个接口:跳高接口
interface Jump{
    public abstract void jump();//强制接口的实现类(子类)必须实现这个方法
    }
猫会跳高了-->实现这个接口
class Cat implements Jump{
    public void catchMOUse(){

        System.out.println("猫抓老鼠")
        }
    @Override
    public void jump(){

public void jump()
        System.out.println("猫可以跳高了。。")
           }
    }

//测试类 
public class InterfaceDemo{
    public static void main (String [] args){
接口不能new 但是接口的具体的子实现类是可以new,接口多态(实际开发中非常多)
        Jump jump = new Cat;(向上转型)
        jump.jump();

        向下转型
        Cat c = (Cat ) jump;
        c.catchMouse();
        }
}

接口的成员特点
成员变量:只能是常量— 存在默认修饰符 public static final(可以省略)
成员方法:只能是抽象方法 —存在默认修饰符 public abstract(可以省略)
构造方法:接口没有构造方法!
//定义接口

interface  Inter{
   // public int num = 10 ;
    public static final int num =10 ;
    //public final  int num2 = 20 ;
    public static final  int num2 = 20 ;
    public abstract  void show() ;
    //void method(){} //不能有方法体
    void method() ;


    //public Inter(){}
}
//接口的实现类
class  InterImpl implements  Inter{


    @Override
    public void show() {
        System.out.println("show InterImpl");
    }


    @Override
    public void method() {
        System.out.println("method InterImpl");
    }
}




//测试类
public class InterfaceDemo2 {
    public static void main(String[] args) {


        //接口多态
        Inter i = new InterImpl() ;
        // i.num = 200;
        System.out.println(Inter.num);   // 接口名.变量名   ---->相当于类名.变量名---->变量名 static修饰
        //i.num2 = 100 ;  //num2:给final修饰  常量
        System.out.println(Inter.num2);
    }
}

接口和抽象类的区别?
1)成员的区别
抽象类:
成员变量:既可以是常量,也可以半两
成员方法:既可以是抽象方法,也可以是非抽象方法
构造方法:无参/有参构造都存在,子类父类需继承,需要分层初始化
接口:
成员变量:只能是常量 public static final(默认修饰符)
成员方法:只能是抽象方法 publicabstract(默认修饰符)
构造方法:没有 – 需要借助子实现类进行实例化(创建对象)
2)关系的区别
类与类:可能是一些抽象类,继承关系,只支持单继承,不支持多继承,但是可以多层继承
类与接口:实现关系 implements
一个类继承另一个类(可能也是抽象类)的同时,还可以实现多个接口
接口与接口:继承关系 extends
支持单继承 也支持多继承,多层继承
3) 设计理念的区别
抽象类–不能实例化
需要通过具体的子类实现类(继承关系)
核心设计理念体现都是一种"is a"的关系(xxx是XX的一种)

接口—不能实例化
需要通过具体的子实现类进行实例化(实现关系implements)
核心设计理念体现的是 事物的一种额外功能
看成一种"like a"的关系

方法形式参数如果引用类型

数组---->需要传递数组对象

具体类----->实际参数,需要传递当前类对象

//学生类
class Student{
    public void studyJavaEE(){
        System.out.println("学生正在学习JavaEE");
    }
}
//定义一个类
class StudentDemo{
    public void method(Student student){//形式参数引用类型:具体类  ---->实际参数需要该Student类的具体对象
        student.studyJavaEE();      //具体的对象(空间地址值)调用成员方法
    }
}
//测试类
public class ArgsDemo {
    public static void main(String[] args) {
        //需要调用StudentDemo类中method方法
        //1)需要创建StudentDemo类对象
        StudentDemo sd = new StudentDemo() ;
        //2)调用方法
        Student s = new Student() ;
        sd.method(s);


        System.out.println("----------------------------------------");
        //可以都匿名对象
        new StudentDemo().method(new Student());
    }
}

抽象类---->抽象类不能实例化,实际参数传递该抽象类的子类对象 (抽象类多态)

//抽象的人类
abstract  class  Person{
    public void work(){
        System.out.println("人都需要工作");
    }
}


//定义一个PersonDemo类
class PersonDemo{
    public void show(Person p){//形式参数一个引用类型:抽象类--->实际参数,需要传递抽象类的子类对象!(抽象类多态)
        p.work() ;
    }
}
//定义一个抽象类的子类(具体类,否则还不能实例化)
//工人类
class Worker extends  Person{
    @Override
    public void work() {
        System.out.println("爱敲代码,爱生活,爱高圆圆!");
    }
}




//测试类
public class ArgsDemo2 {
    public static void main(String[] args) {
        //调用PersonDemo类的show方法
        //1)创建PersonDemo类对象
        PersonDemo pd = new PersonDemo() ;
        //2)调用方法


        //Person p = new Person() ; //抽象类不能实例化(不能创建对象)
       // pd.show(p);
        //抽象类多态
        Person person = new Worker() ;
        pd.show(person);
        System.out.println("------------------------");
        //匿名对象
        new PersonDemo().show(new Worker());
    }
}

接口 ----->接口不能实例化,实际参数需要传递该接口的子实现类对象(接口多态)

//定义一个接口
interface Mary{
    //结婚
    public abstract void mary() ;
}
//定义MaryDemo类
class MaryDemo{
    public void function(Mary mary){//形式参数是引用类型,接口类型---实际参数?需要接口的子实现类对象(接口多态)
        mary.mary();
    }
}
//需要的接口的子实现类
class You implements  Mary{


    @Override
    public void mary() {
        System.out.println("结婚了,很开心...");
    }
}


//测试类
public class ArgsDemo3 {
    public static void main(String[] args) {
        //需要调用MaryDemo类中function方法
        //1)创建MaryDemo类对象
        MaryDemo md = new MaryDemo() ;
        //2)调用方法
      /*  Mary mary = new Mary(); //接口也是抽象的,不能实例化
        md.function(mary);*/


        Mary mary = new You() ; //接口多态
        md.function(mary) ;
        System.out.println("----------------------------------") ;
        //匿名对象
        new MaryDemo().function(new You());
    }
}

方法的返回值问题

1)返回基本类型: 需要什么基本数据类型,使用对应性的类型接收
2)研究引用类型:

具体类: 需要返回的是当前具体类的对象 !

//学生类
class Student{
    public void sutdy(){
        System.out.println("正在学习JavaSE之面向对象");
    }
}
//定义一个StudentDemo类
class StudentDemo{
  /*  public int add(int a,int b){
        return  a+b ;
    }*/
    public Student getStudent(){
        //?
        //如何返回?
        //如果方法的返回值是一个引用类型:具体类,需要返回当前类的对象!
        //Student s = new Student() ;
       // return  s ;
        return  new Student(); //匿名对象
    }
}


//测试类
public class ReturnDemo {
    public static void main(String[] args) {
        //调用StudentDemo类中的getStuent方法
        //1)创建对象
        StudentDemo sd = new StudentDemo() ;
        //2)调用方法
        Student student = sd.getStudent();  //sd.getStudent() 逻辑---创建一个学生
                                            //本质就是Student student = new Student() ;


        student.sutdy();
        System.out.println("-----------------------------------------") ;
        //匿名对象
        //链式编程(自己玩)
        new StudentDemo().getStudent().sutdy();
    }
}

抽象类: 需要返回的是当前抽象类的子类对象(抽象类多态)

//抽象类
abstract  class Person{
    public void work(){
        System.out.println("人都需要工作");
    }
}
//定义一个PersonDemo
class PersonDemo{
    public  Person getPerson(){
       // Person p = new Person() ;
        //return  p;
        //return  new Person() ;


        //抽象类不能new,可以通过抽象类的子类进行实例化
        //抽象类多态
      //  Person p = new Programmer() ;
       // return  p;


        return  new Programmer() ;
    }
}
//定义出现抽象类的子类
class Programmer extends  Person{
    @Override
    public void work() {
        System.out.println("程序员日日夜夜coding...");
    }
}


//测试类
public class ReturnDemo2 {
    public static void main(String[] args) {
        //调用PersonDemo的getPerson()
        PersonDemo pd = new PersonDemo() ;
        Person person = pd.getPerson();//方法的本质---Person person = new Programmer() ;
        person.work() ;
        System.out.println("----------------------------") ;
        //匿名对象
        new PersonDemo().getPerson().work();
    }
}

接口 :需要返回的是接口的子实现类对象(接口多态)

//定义一个接口
interface  Love{
    void love() ;
}
//有一个类LoveDemo
class LoveDemo{
    //成员方法
    public Love getInstance(){ //返回值是接口类型
        // Love love = new Love() ;    //接口不能实例化
        //return  love;


        //方式1:
        //接口多态:需要接口类型---返回接口的子实现类对象
       // Love love  = new LoveImpl() ;
        //return  love ;


        //方式2:匿名对象
        return  new LoveImpl() ;
    }
}
//需要有一个子实现类来实现接口
class LoveImpl implements  Love{


    @Override
    public void love() {
        System.out.println("爱生活,爱Java");
    }
}
//测试类
public class ReturnDemo3 {
    public static void main(String[] args) {
        //调用LoveDemo里面的getInstance()方法
        LoveDemo ld = new LoveDemo() ;
        Love love = ld.getInstance(); //方法本质  --Love love = new LoveImpl() ;
        love.love();


        System.out.println("------------------------------------------") ;
        //匿名对象
        new LoveDemo().getInstance().love();
    }
}

关于类与类 类与接口 接口与接口的关系

Java中最基本单元就是类! ---- Java中只支持单继承(类和类)

类与类: 只支持单继承,不支持多继承,但是多层继承

类与接口:是实现关系,一个类继承另一个类的同时,可以实现多个接口!

class 子类名 extends 父类名  implements 接口1,接口2....{}

接口与接口:(继承关系)-------------->集合:Collection 接口---->List子接口 Set子接口
Map接口----------->HashMap TreeMap
不仅可以单继承,也可以多继承

/*
多层继承
class GrandFather{}
class Father extends GrandFather{}
class Son extends  Father{}
*/
//接口1
interface Inter1{
    public  abstract  void show() ;
}
//接口2
interface  Inter2{
    public abstract  void method();
}
//接口与接口:继承---支持多继承
interface  Inter3 extends  Inter1,Inter2{
          void show2();
}
//父类
class Father {
    public void function(){
        System.out.println("function Father");
    }
}
//子类
class Son extends  Father implements Inter1,Inter2{
    @Override
    public void show() {
        System.out.println("son Show");
    }
    @Override
    public void method() {
        System.out.println("son Method");
    }
}
//子实现类
class  InterImpl implements  Inter3{
    @Override
    public void show() {
    }
    @Override
    public void method() {
    }
    @Override
    public void show2() {
  }
}

//测试类
public class InterfaceDemo {
    public static void main(String[] args) {
        //创建具体的子类对象
        Son s  = new Son() ;
        s.show() ;
        s.method();
        s.function();
    }
}

内部类

一个类A中,有一个类B,将类B就称为类A的内部类,类A就是类B的外部类!
内部类有两种格式
1)成员内部类---->在一个外部类的成员位置(类中,方法外)定义的类
2)局部内部类---->在外部类的局部位置(方法定义中)定义的类

//外部类
class Outer{
    //成员内部类
   /* class Inner{
    }*/
    //外部类的成员方法
    public void show(){
        //局部内部类
        class Inner{
            //局部内部类的成员方法
            public void method(){
            }
        }
    }
}
//测试类
public class InnerClassDemo {
    public static void main(String[] args) {
    }
}

成员内部类:
成员内部类可以访问外部类的成员,包括私有相关的!
如何直接通过外部类去访问内部类的成员呢?(格式 重点)
外部类.内部类名 对象名 = new 外部类名().new 内部类名();

//定义一个外部类
class Outer2{
    //成员变量
    public  int num = 100 ;
    private int num2 = 200;
    //成员内部类
    class Inner2{
        //成员方法
        public  void show(){
            System.out.println(num) ;
            System.out.println(num2) ;
        }
    }
    //外部类的成员方法中
  /*  public void method(){
       // show() ;  调用的本类中的成员方法
       //通过成员内部类对象来访问
        Inner2 inner = new Inner2() ;
        inner.show();
    }*/
}

//测试类
public class InnerClassDemo2 {
    public static void main(String[] args) {
        //创建外部类对象
       // Outer2 outer = new Outer2() ;
       // outer.method(); //间接访问
        // 外部类.内部类名 对象名 = new 外部类名().new 内部类名();
        Outer2.Inner2 oi = new Outer2().new Inner2() ;
        oi.show();
    }
}

成员内部类的修饰符
可以有private修饰,目的是为了数据安全性

伪代码
           人有身体(Body),身体内部有心脏(Heart)
              class Body{

                  //成员内部类 :private修饰 ---保证数据安全性  (集合ArrayList--->私有的成员内部类Itr)
                  private class Heart{

                      public viod method(){}
                  }

                 //成员方法
                  public void operator(){ //手术
                      if(如果你是外科医生){
                          Heart heart = new Heart();
                          heart.method() ;
                      }
                  }
              }

外部类名.成员内部类名 对象名 = new 外部类名().new 内部类名() ;
//成员内部被私有修饰—保证数据安全,上面方式就不能用了

成员内部类—还可以static修饰符(记忆)
1)静态的成员内部类只能外部类的静态成员!
2)静态的成员内部类中无论是静态方法还是非静态方法:访问外部类的成员必须静态
3)想直接通过外部类来访问静态成员内部类的成员信息,访问格式
外部类名.内部类名 对象名 = new 外部类名.内部类名() ;

//外部类
class Outer3{
    //外部类的成员
    public int num  = 10;
    public static int num2 = 20 ;


    //提供一个静态的成员内部类
    static class Inner3{
        //非静态方法
        public void show(){
            //System.out.println(num);
            System.out.println(num2) ;
        }
        //静态的方法
        public static void show2(){
            //System.out.println(num);
            System.out.println(num2);
        }
    }
}
//测试类
public class InnerClassDemo3 {
    public static void main(String[] args) {


        //外部类名.成员内部类名 对象名 = new 外不类名().new 内部类名() ; --->仅仅适用于成员内部类是非静态
       // Outer3.Inner3 oi = new Outer3().new Inner3() ;


        //外部类名.内部类名  对象名 =  new 外部类名.内部类名() ;
        //将静态的成员内部类---看成是外部类的静态成员方法---直接使用外部类访问
        Outer3.Inner3 oi = new Outer3.Inner3();
        oi.show();
        oi.show2(); //静态方法不推荐使用静态名来访问
        System.out.println("------------------------------");
        //show2()是静态的
        Outer3.Inner3.show2() ;
    }
}

局部内部类

//特点和成员内部类一样,局部内部类也可以直接外部类的包括私有!
class Outer{
public void method(){
class Inner{
public void show(){
//局部变量
int num = 20 ;//jdk7(jdk7以前):此时num必须显示的加入

局部内部类的面试题
局部内部类
1)也可以访问外部类的成员包括私有
2)面试题:局部内部类访 访问它的成员方法里面的局部变量,局部变量有什么特点?(重点)
jdk7以前(包括jdk7):局部内部类访问局部变量的时候,局部变量必须使用final修饰!为什么?
局部变量它随着方法调用而存在,随着方法调用结束而消失,但是现在是通过局部对象调用它的成员方法还在使用这个局部变量
局部变量必须为常量(加入final)—局部内部类对象不会立即消失,等待gc回收
jdk8以及jdk8以后 jvm已经对这个局部变量优化 ,将final省略了

//外部类
class Outer{
    //成员
    private int num = 20 ;
    public int num2 = 50 ;

    //成员方法
    public void method(){
        //局部内部类
        class Inner{
            //局部内部类的成员方法
            public void show(){
                //局部变量
                int x = 100 ;

                System.out.println(num2) ;
                System.out.println(num);
                System.out.println(x);
            }
        }
        //访问show()方法
        Inner inner = new Inner() ;
        inner.show();

    }
}
//测试类
public class InnerClassDemo {
    public static void main(String[] args) {
        //创建外部类对象,调用成员方法method
        Outer outer = new Outer() ;
        outer.method();
    }
}

匿名内部类

匿名内部类: 没有名字的类
应用范围: 在局部位置中的(方法定义中或者声明上)
匿名内部类的格式:

new 类名或者一个接口名(){
重写方法(){
...
}
}

匿名内部类的本质:就是继承该类(抽象类)或者是实现类了该接口的子类对象!

//外部类
class Outer{
    //外部类的成员方法
    public void method(){
        //使用匿名内部类的格式将Love接口里面的show方法实现了
     /*   class LoveImpl implements  Love{

            @Override
            public void show() {
                System.out.println("show Love");
            }
        }

        //接口多态
        Love love = new LoveImpl() ;
        love.show();*/
        /*
                new 类名或者一个接口名(){
                   重写方法(){
                       ...
                   }
               };
            */
        //直接使用匿名内部类
       /* new Love(){

            //重写接口的方法
            @Override
            public void show() {
                System.out.println("show Love...");
            }

            @Override
            public void show2() {
                System.out.println("show2 Love...");
            }
        }.show();

        new Love(){

            //重写接口的方法
            @Override
            public void show() {
                System.out.println("show Love...");
            }

            @Override
            public void show2() {
                System.out.println("show2 Love...");
            }
        }.show2();*/

        //当接口中或者抽象类中有多个抽象方法的时候,匿名内部类使用比较麻烦,通过下面这种简化访问代码量
        //可以给 new 类名或者接口名(){.重写方法..} 起一个名字(对象名),使用这个对象名可以访问
        Love love  = new Love(){
            @Override
            public void show() {
                System.out.println("show Love");
            }

            @Override
            public void show2() {
                System.out.println("show2 Love");
            }
        };
        love.show();
        love.show2();

    }
}

//测试类
public class InnerClassDemo {
    public static void main(String[] args) {
        //创建外部类对象
        Outer outer = new Outer() ;
        outer.method();
    }
}
//有一个抽象类
abstract  class Person{
    public  abstract  void work() ;
}
//外部类
class Outer2{
    //一个成员方法
    public void function(){
        //在这个局部位置,需要有个局部内部类,继承自Person,重写work
       /* class Progamer extends Person{

            @Override
            public void work() {
                System.out.println("程序员不断的充电,敲代码!");
            }
        }
        //调用work
        //抽象类多态
        Person person = new Progamer() ;
        person.work();*/
        //匿名内部类的格式
        /*
        * new 类名(){
        *   重写方法(){
        *               ..
        *       }
        * };
        * */
        new Person(){

            @Override
            public void work() {
                System.out.println("人的工作性质不同...");
            }
        }.work(); ;
    }

}


//测试类
public class InnerClassDemo2 {
    public static void main(String[] args) {

        //创建外部类对象
        Outer2 outer2 = new Outer2() ;
        outer2.function();
    }
}

匿名内部类在开发中的使用场景:形式参数问题

形式参数是抽象类的情况

 形式参数问题
       如果方法的形式参数是一个抽象类,调用方法的时候实际参数需要这个抽象类的子类对象!
//抽象类
abstract  class Person{
    public abstract  void work() ;
}
//定义PersonDemo类
class PersonDemo{
    public void show(Person p){//引用类型--抽象类---需要抽象类子类对象
        p.work();
    }
}
//定义一个类(具体类),继承Person
class Progammer extends  Person{

    @Override
    public void work() {
        System.out.println("程序员日日夜夜敲代码...");
    }
}
//测试类
public class ArgsDemo {
    public static void main(String[] args) {
        //调用PersonDemo类里面的show方法
        PersonDemo pd = new PersonDemo() ;
        //Person p = new Person() ;//抽象类不能new
        //抽象类多态
        Person p = new Progammer() ;
        pd.show(p);
        System.out.println("--------------------------------------") ;
        //方式2:可以使用抽象类的匿名内部类
        /**
         * new 抽象类名(){
         *     重写方法
         * }
         */
        pd.show(new Person() {
            @Override
            public void work() {
                System.out.println("人都需要工作...");
            }
        });
    }
}

形势参数是接口的情况

形式参数问题
 *        如果方法的形式参数是一个接口,调用方法的时候实际参数需要这个接口的子实现类对象!
 */
//有一个接口
interface Mary{
    public abstract void mary() ;//接口中有且仅有一个抽象方法,这个接口称为"函数式接口"
}
//定义一个类
class MaryDemo{
    public void method(Mary mary){//需要使用接口多态,创建具体的子实现类对象
        mary.mary();
    }
}
//定义接口的子实现类实现这个接口
class You implements  Mary{

    @Override
    public void mary() {
        System.out.println("结婚了,很开心...");
    }
}

//测试类
public class ArgsDemo2 {
    public static void main(String[] args) {
        //调用MaryDemo里面的method方法
        MaryDemo md = new MaryDemo() ;
        //接口多态
        Mary mary = new You() ;
        md.method(mary);
        System.out.println("------------------------------------------");

        //接口匿名内部类
        md.method(new Mary() {
            @Override
            public void mary() {
                System.out.println("要结婚了,很开心...");
            }
        });
        System.out.println("-------------------------------------------");

        //jdk8的一个新特性:拉姆达表达式 (针对函数式接口)
        md.method(
           //拉姆达表达式
            ()-> {
                System.out.println("要结婚了,很开心...");
            }
        );
    }
}

匿名内部在开发中的使用 :返回值问题

返回值是抽象类的情况
方法的返回值是一个抽象类,需要返回该抽象类的子类对象

*/
abstract  class Person{
    public  abstract  void work() ;
}
class PersonDemo{
    public Person show(){
        //需要返回的抽象类的子类对象 (抽象类多态)
        //Person p = new Worker() ;
       // return  p;
        //return  new Worker() ;

        //抽象类的匿名内部类
        return  new Person(){

            @Override
            public void work() {
                System.out.println("打工人爱工作,爱生活,爱高圆圆");
            }
        };
    }
}
//定义一个Person的子类
/*class Worker extends  Person{

    @Override
    public void work() {
        System.out.println("工人爱工作,爱生活...");
    }
}*/
//测试类
public class ReturnDemo {
    public static void main(String[] args) {
        //访问PersonDemo的show
        PersonDemo pd = new PersonDemo() ;
        Person person = pd.show(); //方法的本质---->new 子类名() ;
        person.work() ;

    }
}

方法的返回值是一个接口,需要返回该接口的子实现类对象!

*/
//接口
interface  Inter{
    void love() ;
}
//InterDemo类
class InterDemo{
    public Inter function(){

        //要么
        //Inter i = new InterImpl() ;
       // return  i ;
        //匿名对象
        //return  new InterImpl() ;

        //接口的匿名内部类
        return  new Inter() {
            @Override
            public void love() {
                System.out.println("love Inter....");
            }
        };

        //实现的接口中只有一个抽象方法 ---可以jdk的拉姆达表达式  -> 函数
        //return () -> System.out.println("love Inter....");


    }
}
//需要有个接口的子实现类
/*class InterImpl implements  Inter{

    @Override
    public void love() {
        System.out.println("love InterImpl...");
    }
}*/


//测试类
public class ReturnDemo2 {
    public static void main(String[] args) {
        //创建InterDemo对象
        InterDemo id = new InterDemo() ;
        Inter inter = id.function(); //方法本质--->创建接口子实现类对象
        inter.love();
    }
}

选择排序

使用数组0角标对应的元素依次和后面的元素比较,小的往前放,第一次比较完毕,最小出现在最小索引处!
 */
//测试类
public class ArrayTest {
    public static void main(String[] args) {

        //提供一个数组,静态初始化
        int[] arr = {24,69,87,56,13} ;
        System.out.println("排序前:") ;
        String str = printArray(arr) ;
        System.out.println(str) ;
        System.out.println("------------------------------------") ;
        //第一次比较
      /*  int x = 0 ;  //x=0
        for(int y = x+1; y < arr.length ;y++){ //y = 1
            //遍历数组:使用前面的元素和后面的元素比较
            if(arr[x]>arr[y]){  //ar[0]   arr[1]  arr[2]
                //中间变量:
                int temp = arr[x] ;
                arr[x] = arr[y] ;
                arr[y] = temp ;
            }
        }
        System.out.println("第一次比较完毕后:" ) ;
        //遍历
        String str2 = printArray(arr) ;
        System.out.println(str2) ;
        System.out.println("--------------------------------------------") ;
        //第二次比较
        x = 1 ;
        //遍历数组后面角标的对应的元素
        for(int y  = x +1 ; y< arr.length ; y ++){
            if(arr[x] > arr[y]){
                int temp = arr[x] ;
                arr[x] = arr[y] ;
                arr[y] = temp ;
            }
        }
        System.out.println("第二次比较后:");
        System.out.println(printArray(arr)) ;
        System.out.println("--------------------------------------------") ;

        //第三次比较
        x = 2 ;
        //遍历数组后面角标的对应的元素
        for(int y  = x +1 ; y< arr.length ; y ++){
            if(arr[x] > arr[y]){
                int temp = arr[x] ;
                arr[x] = arr[y] ;
                arr[y] = temp ;
            }
        }
        System.out.println("第三次比较后:");
        System.out.println(printArray(arr)) ;
        System.out.println("--------------------------------------------") ;
        //第四次比较
        x = 3 ;
        //遍历数组后面角标的对应的元素
        for(int y  = x +1 ; y< arr.length ; y ++){
            if(arr[x] > arr[y]){
                int temp = arr[x] ;
                arr[x] = arr[y] ;
                arr[y] = temp ;
            }
        }
        System.out.println("第四次比较后:");
        System.out.println(printArray(arr)) ;


*/

        //上面代码重复度高
        //x=0,1,2,3---->最终比较的次数:数组长度-1次
        /**
         *  for(int y  = x +1 ; y< arr.length ; y ++){
         *             if(arr[x] > arr[y]){
         *                 int temp = arr[x] ;
         *                 arr[x] = arr[y] ;
         *                 arr[y] = temp ;
         *             }
         *         }
         *         循环了四次
         */
       /* for(int x = 0 ; x < arr.length - 1;x++){//比较的次数
            for(int y = x+1; y < arr.length;y++){ //元素进行判断 比较
                //如果前面的元素比较后面元素大,将后面的元素往前放
              if(arr[x] > arr[y]){
                  int temp = arr[x] ;
                  arr[x] = arr[y] ;
                  arr[y] = temp ;
              }
            }
        }
        //最终
        System.out.println("排序后:") ;
        System.out.println(printArray(arr));
        System.out.println("-----------------------------------------");*/
        System.out.println(printArray(arr)) ;
        int[] arr2 = selectSort(arr);
        //System.out.println(arr2);
        System.out.println(Arrays.toString(arr2));//Arrays数组工具类toString--->将数组转换成String
        //System.out.println(printArray(arr)) ;
    }

    //定义一个选择排序的方法
    public static int[] selectSort(int[] arr){
        for(int x = 0 ; x < arr.length - 1;x++){//比较的次数
            for(int y = x+1; y < arr.length;y++){ //元素进行判断 比较
                //如果前面的元素比较后面元素大,将后面的元素往前放
                if(arr[x] > arr[y]){
                    int temp = arr[x] ;
                    arr[x] = arr[y] ;
                    arr[y] = temp ;
                }
            }
        }
        return arr;
    }

    //遍历数组  --->没有返回值类型void--->直接输出
    public static String printArray(int[] arr){
        //定义一个字符串
        String s = "" ; //结果变量
        s+= "[" ;
        //遍历数组
        for(int x = 0 ; x < arr.length ; x++){
            if(x==arr.length-1){
                //取到最大索引值,对应最后一个元素
                s+=arr[x] ;
                s+="]" ;
            }else{
                //中间角标对应的元素
                s+= arr[x] ;
                s+=", ";
            }
        }
        return s;
    }

}

思路图解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值