static 关键字,接口,内部类,多态

static 关键字概述

关键字可以使用的位置:类,成员变量,局部变量,成员方法,构造方法

static:表示静态的,可以修饰成员变量,成员方法。

static 所修饰的方法和变量会存储在方法区内,属于类,不再属于对象自己,只有一份。

package demo01_static关键字;

public class Student {

```
String name;
static String room = "314"; //所在教室 用static修饰的成员变量 属于类  有时也叫静态变量  不再属于对象自己  被所有对象共享

public Student(String name) {
    this.name = name;
}
```

}
package demo01_static关键字;

public class Test {

```
public static void main(String[] args) {
    Student one = new Student("科比");
    one.room = "514教室";
    System.out.println(one.name);
    System.out.println(one.room);
    Student two = new Student("韦德");
    System.out.println(two.name);
    System.out.println(two.room);
}
```

}

static关键字访问方式

1.可以创建对象,通过对象访问,并且如果是成员变量的话,可以通过调用修改。方法不能重写。

2.使用类名调用(支持)

静态属性和静态方法可以被extends方式继承,但是不可以被implements方式继承。

static关键字内存分配时机

一,在程序运行期间,在第一次创建对象时,会给该静态成员先分配内存,然后再执行构造方法。

顺序:

1.给静态成员分配内存

2.给普通成员分配内存

3.执行构造方法

注:静态成员只会被加载一次,静态成员会比对象先进入内存。

二,在程序运行期间,第一次访问该类静态成员时,jvm会给该类的所有静态成员分配内存。

第一次使用该类的时候,静态成员会和类一起被加载。

静态成员访问规则

package demo02_static关键字_静态成员访问规则;

public class Student {
    int age = 18;
    String name;
    static String room = "314"; //所在教室 用static修饰的成员变量 属于类  有时也叫静态变量  不再属于对象自己  被所有对象共享

```
public Student(String name) {
    this.name = name;
}

public static void study(){//静态方法
    System.out.println("学好java,高薪就业");
```

//        System.out.println(age);//编译报错 静态方法不能访问非静态成员  因为静态成员比对象先进入内存
    }
    

```
public void show(){
    System.out.println(room);//在非静态方法中可以访问静态成员
}
```

}
package demo01_static关键字;

public class Student {

```
String name;
static String room = "314"; //所在教室 用static修饰的成员变量 属于类  有时也叫静态变量  不再属于对象自己  被所有对象共享

public Student(String name) {
    this.name = name;
}

public static void study(){//静态方法
    System.out.println("学好java,高薪就业");
}
```

}

static关键字-静态代码块

1.定义在类种方法外,用static修饰的一组代码

2.特点:静态代码块在创建对象时,或者第一次使用该静态类静态成员时会被执行而且只执行一次,并且在构造方法之前执行。

3.作用:静态代码块就是为静态变量进行初始化的,因为有时候静态变量初始化代码不是一句就能够完成的。

package demo01_static关键字;

public class Student {

```
String name;
static String room = "314"; //所在教室 用static修饰的成员变量 属于类  有时也叫静态变量  不再属于对象自己  被所有对象共享

public Student(String name) {
    this.name = name;
}
```

}
package demo01_static关键字;

public class Test {

```
public static void main(String[] args) {
    Student one = new Student("科比");
    one.room = "514教室";package demo03_static关键字_静态代码块;
```

public class Test {

```
public static void main(String[] args) {
```

//        Student one = new Student(18);
//        Student two = new Student(20);
//        System.out.println(Student.room);
        System.out.println(Student.arr[0]);
        System.out.println(Student.arr[1]);
        System.out.println(Student.arr[2]);

```
    System.out.println(Student.arr[0]);//和第一次输出的一样,因为静态代码块只执行一次
}
```

}
package demo03_static关键字_静态代码块;

import java.util.Random;

public class Student {
    int age;

```
static String room = "314教室";

static int[] arr = new int[10];//静态变量

static {
    System.out.println("静态代码块");
    Random random = new Random();
    for (int i = 0; i < arr.length; i++) {
        arr[i] = random.nextInt(100) +  1;
    }
}

public Student(int age) {
    this.age = age;
    System.out.println("有参构造方法");
}

/**
 * 需求:为arr每一个元素初始化一个1-100的随机数
 * 1.生成一个1-100的随机数 Random
 * 2.遍历arr数组 将随机数赋值给arr数组中的每一个元素
 */
```

//    Random random = new Random();
//    fo
//    public Student(){//只能用静态代码块为静态变量初始化
//        Random random = new Random();
//        for (int i = 0; i < arr.length; i++) {
//            arr[i] = random.nextInt(100) +  1;
//        }
//    }
}

```
    System.out.println(one.name);
    System.out.println(one.room);
    Student two = new Student("韦德");
    System.out.println(two.name);
    System.out.println(two.room);
}
```

}




开发中static的应用

static修饰的成员属于类的,被所有对象共享的,在实际开发中如果有一些数据和方法是被大家共用的,就可以使用static修饰,可以直接使用类名进行调用

class Const{public static final double PI= 10//定义常量π,并且被final修饰的变量名为常量,全部字母用大写

//创建一个方法用来求最大值public static int max (int[] arr){

   	     int max = arr[0];for(int i = 1 ; i <arr.length; i ++ ){if(arr[i]>max){

​				max = arr[i];}return max;}}

}
class Test{
    public static void main(String[] args){
        System.out.println(Const.PI);//调用公共类中的常量
        int[] arr = {1,2,3,4}
        System.out.println(max(arr));//调用公共类中的方法
    }
}

接口

1.比抽象类还要抽象的一种引用类型,方法的集合,在jdk1.7时只能定义抽象方法。jdk1.8之后接口 可以定义默认方法和静态方法。

2.定义及内容

通过interface关键字定义接口

格式:

public interface Animal{

}

使用:接口不可以创建对象,接口有一个实现类,使用implemets来实现接口,类似于继承。

实现类必须重写接口类中的全部抽象方法。

public interface Animals{
    public abstract void eat();//抽象方法
    public abstract void sleep();
}
public class Cat implements Animals{
    //必须重写接口类里面的所有抽象类
    public void eat(){
        System.out.println("小猫吃鱼");
    }
    public void sleep(){
        System.out.println("小猫睡觉");
    }
}
public class Test{
    public static void main(String[] args){
        Cat cat = new Cat;
        cat.eat();
        cat.sleep();
    }
}

接口类里面的方法:抽象方法,默认方法,静态方法。

public interface Animals{
    //抽象方法
    public abstract void  eat();
    //默认方法
    public default void show(){}//可以被子类继承,子类可重写也可以不重写
    //静态方法
    public static void demo(){}//不能够被接口继承,可以通过接口名调用,但是可以extends方式继承。
    public static final int AGE = 10;//静态属性(此刻AGE是常量,被final保护)
}
public class Dog implements Animals{//实现类
    //必须重写抽象方法
    public void eat(){};
    //默认方法可以重写也可以不重写
    //静态方法不可以被继承
    
}
public class Test{
    Dog dog = new Dog();
    dog.eat();//抽象类被继承重写。
    dog.show();//默认类被继承,但是Dog没有重写。
    dog.demo//报错,因为静态类不会被继承,不可以通过此方式调用。
    Animals.demo//通过接口类名调用静态方法。
    Animals.AGE//通过接口类名调用静态属性。
    
}

默认方法的意义:解决接口升级的问题,如果在程序已经投入使用阶段进行维护添加方法,可以使用默认方法添加,如果使用抽象方法将会引起程序报错,产生损失。

接口的作用及意义:

解决java单继承的弊端。子类可以继承一个类的同时,实现一个或者多个接口。

子类必须是先继承,后实现接口,并且实现接口数量不限制。

子类实现多接口的冲突

常量:若实现的多接口类中有相同名称常量,实现类种调用该常量会引起报错

抽象方法:若实现的多接口类有相同的名称的抽象方法,只需要重写一次。

默认方法:若实现的多接口类中有相同名称的默认方法,只需要重写一次,确认最终版本。

静态方法:若实现的多接口类中有相同名称的静态方法,不会报错,也无需重写,因为不会被子类继承

子类先继承后实现中被继承类和接口类的冲突

常量:若继承类和接口类中有相同名称的常量,子类调用时报错

抽象方法:改写一次,因为是先继承,继承时候改写继承父类中的抽象方法之后,默认为此改写的抽象方法也将接口类中的抽象方法改写完毕(如果继承父类中某一个非抽象方法和接口类中的抽象方法重名,则无需改写,因为默认先继承的为接口类中的改写完毕版本)

默认方法:不会报错,和抽象方法类似,默认为继承父类的同名方法将默认方法改写

静态方法:不会报错,接口类中的静态方法不会被继承,继承父类会继承,不会产生编译错误。

单接口继承多接口

和先继承后实现的情况相同

多态(java三种特性:继承,封装,多态)

多态的概念:同一种行为表现出不同的状态

格式

父类引用指向子类对象(左父右子)

父类 名称 = new 子类

多态的前提是继承,没有继承就没有多态

多态时访问成员的特点

总体规则是:当访问是都是访问父类的,不能访问子类特有的成员。(子类中除了子类改写了父类的方法可以被访问,其余的都不行!继承下来的属性(有参构造)可以)

当访问成员变量,访问的都是父类的,看得是引用。

当访问方法时候,访问的都是子类的,看得是对象。

class Animals{
    int age = 15public void eat(){}
}
class Cat extends Animals{
    int age 3;
    public void eat(){
        
    }
}
class Test {
    Animals animals  = new Cat();
    System.out.println(animal.age);//调用的是父类的
    animals.eat();//调用的是子类的
}

多态的几种形式

1.父类的多态

2.接口类的多态

3.父抽象类的多态

使用方法一样。

多态的几种使用方式

1.变量的多态

Animals animals = new Cat();

2.方法参数的多态,方便接口实现双向

class Test{
    public static void main(String args[]){
        Cat cat = new Cat();
        shouEat(cat);
        Animals animals = new Dog();
        shouEat(animals);
        //以上两种方法都可以
    }
    public static void shouEat(Animals animals){//实参是这个父类的任何一个子类,就可以调用此方法。
        animals.eat();
        //此方法的好处是,任何子类都可以使用这个方法,若形参是某个子类的对象的话,一个子类调用这个方法,就得再写一个这个方法。
        
    }
}
3.方法返回值的多态,方便接口实现双向
public static Animals getAnimals(){//可以返回任何的Animals 子类
	Cat cat = new cat();
	return cat;
}

多态的好处和弊端

1.弊端:不能够访问子类的特有成员

2.好处:有利于程序扩展,主要体现在与方法参数的多态和方法返回值的多态上。

多态的转型

1.向上转型:

Animals animals = new Cat();

弊端:不能够访问子类特有成员。

2.向下转型(消除多态弊端)

class Test{
    public static void main(String[] args){
        Animals animal = new Cat;
        //向下转型有风险,需要判断 关键字 instanof
        if(animal instanceof Cat{
            Cat cat = (Cat)animal;
        }
        Dog dog = (Dog)animal;//编译通过  java.lang.ClassCastException  类转换异常
        //向下转型前,先用向上转型。
        
    }
}


笔记本电脑案例

package com.day02.笔记本电脑案例;

public class Computer {
    public void start() {
        System.out.println("开机!");
    }

    public void off() {
        System.out.println("关机!");
    }

    public static void computerPei(USB usb) {
        usb.run();

    }
}
package com.day02.笔记本电脑案例;

public class Keyboard implements USB {
    public void run(){
        System.out.println("敲打,化身键盘侠,刺啦~划拉~wu~");
    }
}
package com.day02.笔记本电脑案例;

public class Mouse implements USB {
    public void run(){
        System.out.println("移动操控哔哔哔,丢丢丢~");
    }
}
package com.day02.笔记本电脑案例;

public interface USB {
    public abstract void run() ;
}
package com.day02.笔记本电脑案例;

public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.start();
        USB usbmouse = new Mouse() ;//Mouse mouse = new Mouse();都可以
        computer.computerPei(usbmouse);
        Keyboard keyboard = new Keyboard();
        computer.computerPei(keyboard);
        computer.off();

    }
}


内部类

1.定义在类中的类

​ 成员内部类:正常的内部类

​ 局部内部类:定义在成员方法中的内部类

​ 匿名内部类:

成员内部类:

class Outer{
	private int a = 100;
    class Insid {
        public void show(){
            System.out.println(a)//内部类可以访问外部类的成员属性,包括私有的。
        }
    }
}
class Tets{
    main{
        Outer.Insid insid = new Outer().new Insid();//内部类对象的创建
        insid.show();
    }
}

局部内部类:
定义在方法中的内部类
class Outer{
	public void show(){
		final int a = 100;
        class Insid{//局部内部类
              sout(a)//局部内部类访问局部变量的时候,此变量必须是final 方法和类的生存周期不同的原因
        }
		Inside inside = new Inside();//局部内部类创建对象只能在方法中
		inside.demo();
	}
	
}
class Test{
	mian{
		Outer outer = new Outer();
		outer.show();
	}
}
匿名内部类:省去了一个变量(引用),代码辨识度太差。
class Test{
	mian{
		Cat cat = new Cat();
		cat.eat();
		Animals animal = new Cat();
		animal.eat();
		/*
			匿名内部类
            new 父类/父类接口(){
            	重写抽象方法
            }
		*/
        new Animals(){
        	public void eat(){
        		sout("hjsakd";
        	}
        }.eat();
	}
}

猜你喜欢

转载自blog.csdn.net/qq_41371264/article/details/103599634