目录
静态成员
mian方法
多态
抽象类
接口
内部类
成员内部类
静态内部类
方法内部类
匿名内部类
Cat.class
package Animal;
public class Cat {
// 定义静态成员变量
public static String name;
public static int age = 5;
// 定义静态成员方法
public static void eat() {
System.out.println("猫吃鱼");
}
}
测试类
import Animal.Cat;
public class Main {
public static void main(String[] args) {
Cat c = new Cat();
// 访问静态成员变量,可以实例化调用,也可以直接 类名. 调用
c.name = "咪咪";
System.out.println(c.name);
System.out.println(c.age);
System.out.println(Cat.name);
// 访问静态成员方法
Cat.eat(); // 猫吃鱼
c.eat(); // 猫吃鱼
}
}
static修饰的静态成员访问特点
Cat.class
package Animal;
public class Cat {
// 静态成员变量
public static String name = "咪咪";
// 非静态成员变量
int age = 5;
// 静态成员方法
public static void eat() {
System.out.println("猫吃鱼");
System.out.println("我想访问name,是可以的,name值是" + name);
// System.out.println("但是我想访问age,发现是不可以的,因为age是非静态成员属性" + age);
}
// 非静态成员方法
public void catchMouse() {
System.out.println("猫会抓老鼠");
System.out.println("访问静态成员变量name:" + name);
System.out.println("访问非静态成员变量age:" + age);
}
}
测试类
import Animal.Cat;
public class Main {
public static void main(String[] args) {
Cat c = new Cat();
// 访问静态成员方法(推荐直接 类名. 调用)
Cat.eat();
// 访问非静态成员方法(只能通过实例化调用)
c.catchMouse();
}
}
定义一个完整的常量
public static final 数据类型 常量名 = 常量值;
Cat.class
package Animal;
public class Cat {
// 常量
public static final int SUCCESSCODE = 200;
}
测试类
import Animal.Cat;
public class Main {
public static void main(String[] args) {
// 访问静态常量(推荐直接 类名. 调用就行,也可以实例化调用)
System.out.println(Cat.SUCCESSCODE); // 200
}
}
public static void main(String[] args) { ... }
注意:
Mian.class
import Animal.Cat;
public class Main {
// 静态成员变量
static int num = 100;
// 非静态成员变量
int count = 999;
public static void main(String[] args) {
System.out.println(num); // 100
Main main = new Main();
System.out.println(main.count); // 999
}
}
给mian方法传入参数
Mian.class
public class Main {
public static void main(String[] args) {
for(int i = 0;i < args.length;i++) {
System.out.println(args[i]); // 1 2 3
}
}
}
多态的前提与体现
Animal.class
package Animal;
public class Animal {
private String name;
private int age;
public String type = "分类";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat() {
System.out.println("东西都需要吃");
}
}
Cat.class
package Animal;
// 1. 首先有继承或者实现关系
public class Cat extends Animal {
String skill = "抓老鼠";
// 2. 存在方法重写
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
测试类
import Animal.Animal;
import Animal.Cat;
public class Main {
public static void main(String[] args) {
// 3. 有父类引用指向子类对象(左父右子)
Animal c = new Cat();
// 访问成员变量,规则是 编译(就是写代码阶段,编辑器会报错)看左,执行看左
// c.skill // 编译阶段就会报错
c.setName("动物名");
System.out.println(c.getName()); // 动物
System.out.println(c.type); // 分类
// 访问成员方法,规则是 编译看左,执行看右
c.eat(); // 猫吃鱼
}
}
多态优缺点
Animal.class
package Demo;
public class Animal {
public void eat() {
System.out.println("动物都需要吃");
}
public void UseEat(Animal animal) {
animal.eat();
}
}
Dog.class
package Demo;
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗狗吃骨头");
}
}
Cat.class
package Demo;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
测试类
import Demo.Animal;
import Demo.Cat;
import Demo.Dog;
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
animal.UseEat(new Cat()); // 猫吃鱼
animal.UseEat(new Dog()); // 狗狗吃骨头
}
}
多态转型
Animal.class
package Demo;
public class Animal {
public void eat() {
System.out.println("动物都需要吃");
}
}
Cat.class
package Demo;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
// 猫类自己特有的成员方法
public void catchMouse() {
System.out.println("猫咪会抓老鼠");
}
}
测试类
import Demo.Animal;
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Animal animal = new Cat(); // 多态
animal.eat(); // 可以访问重写的成员方法
// animal.catchMouse(); // 但是访问不了子类特有的成员方法。就需要向下转型成Cat,这样才能调用子类特有的成员
Cat c = (Cat) animal;
c.catchMouse(); // 猫咪会抓老鼠 向下转型后就可以访问了
}
}
public abstract void 抽象方法名(); // 抽象方法没有方法体,抽象方法只能在抽象类中
abstract class 抽象类名 { }; // 抽象类
举例
Animal.class
package Demo;
// 抽象类,用 abstract 关键字修饰
public abstract class Animal {
// 抽象方法,用 abstract 关键字修饰,且没有方法体。实现类必须重写抽象方法
public abstract void eat();
}
Cat.class
package Demo;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
// 猫类自己特有的成员方法
public void catchMouse() {
System.out.println("猫咪会抓老鼠");
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat(); // 猫吃鱼
}
}
抽象类的特点
Animal.class
package Demo;
// 抽象类,用 abstract 关键字修饰
public abstract class Animal {
// 抽象方法,用 abstract 关键字修饰,且没有方法体。实现类必须重写抽象方法
public abstract void eat();
// 抽象类中也可以有非抽象方法
public void run() {
System.out.println("动物都会奔跑");
}
}
Cat.class
package Demo;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat(); // 猫吃鱼
cat.run(); // 动物都会奔跑
}
}
Animal.class
package Demo;
// 抽象类,用 abstract 关键字修饰
public abstract class Animal {
// 抽象方法,用 abstract 关键字修饰,且没有方法体。实现类必须重写抽象方法
public abstract void eat();
// 抽象类中也可以有非抽象方法
public void run() {
System.out.println("动物都会奔跑");
}
}
Cat.class
package Demo;
public abstract class Cat extends Animal {
}
LiHuaMao.class
package Demo;
public class LiHuaMao extends Cat {
@Override
public void eat() {
System.out.println("小狸花吃老鼠");
}
}
测试类
import Demo.LiHuaMao;
public class Main {
public static void main(String[] args) {
LiHuaMao liHuaMao = new LiHuaMao();
liHuaMao.eat(); // 小狸花吃老鼠
liHuaMao.run(); // 动物都会奔跑
}
}
Animal.class
package Demo;
// 抽象类,用 abstract 关键字修饰
public abstract class Animal {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 抽象方法,用 abstract 关键字修饰,且没有方法体。实现类必须重写抽象方法
public abstract void eat();
// 抽象类中也可以有非抽象方法
public void run() {
System.out.println("动物都会奔跑");
}
// 抽象类也可以有构造方法,用于子类数据初始化
public Animal() {}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
}
Cat.class
package Demo;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat cat = new Cat("咪咪",5);
System.out.println(cat.getName()); // 咪咪
System.out.println(cat.getAge()); // 5
}
}
abstract关键字注意点(记结论就行,原因不用记)
public interface 接口名 { }
public class 类名 implements 接口名 { }
创建接口
Animal.class(这个是接口)
package Demo;
public interface Animal {
// 接口中只能有常量,前面默认添加 public static final。因为加了 static ,所以可以直接 类名. 调用
String name = "动物名";
public static final int age = 5; // 跟上面写是一样的,可以看出前面的都是灰色的,可写可不写
// 接口中JDK8之前只能有抽象方法,但是JDK8之后可以有非抽象方法(但是需要使用default关键字修饰)
public abstract void eat(); // 接口中的抽象方法,前面默认会自动添加public abstract
void drink();
public default void run() {
System.out.println("动物都会奔跑");
}
}
Cat.class
package Demo;
public class Cat implements Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void drink() {
System.out.println("猫喝水");
}
}
实现类
import Demo.Animal;
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.run(); // 动物都会奔跑
cat.eat(); // 猫吃鱼
cat.drink(); // 猫喝水
System.out.println(Animal.name); // 动物名
}
}
举例:
Animal.class(这个是接口)
package Demo;
public interface Animal {
// 接口中只能有常量,前面默认添加 public static final。因为加了 static ,所以可以直接 类名. 调用
String name = "动物名";
public static final int age = 5; // 跟上面写是一样的,可以看出前面的都是灰色的,可写可不写
// 接口中JDK8之前只能有抽象方法,但是JDK8之后可以有非抽象方法(但是需要使用default关键字修饰)
public abstract void eat(); // 接口中的抽象方法,前面默认会自动添加public abstract
void drink();
public default void run() {
System.out.println("动物都会奔跑");
}
}
Cat.class
package Demo;
public class Cat implements Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void drink() {
System.out.println("猫喝水");
}
}
测试类
import Demo.Animal;
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Animal cat = new Cat(); // 这个就是接口多态
cat.eat(); // 猫吃鱼(多态访问成员方法规则:编译看左,执行看右。所以输出的是猫的吃方法)
}
}
类与接口的小区别
比如:在一个A类的内部定义一个类B,类B就称为内部类,类A相应的称为外部类
public class 外部类名 {
public class 内部类名 {
...
}
}
内部类访问特点
Cat.class
package Demo;
// 外部类
public class Cat {
private String name = "猫咪";
private int age = 5;
// 内部类
public class LiHuaMao {
private String name = "狸猫";
public void dis() {
System.out.println("我是一只小"+ name + ",在古代我可以换太子。今年我" + age + "岁了");
}
}
// 外部类如果想使用内部类,必须实例化内部类才能使用
public void Xxx() {
LiHuaMao liHuaMao = new LiHuaMao();
liHuaMao.dis();
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.Xxx(); // 我是一只小狸猫,在古代我可以换太子。今年我5岁了
}
}
内部类分类
作为类中的一个成员。定义在类中成员方法外,跟成员方法,成员属性(又叫成员变量)同级的
package Demo;
// 外部类
public class Cat {
// 成员属性
private String name = "猫咪";
private int age = 5;
// 内部类(成员内部类,跟成员方法,成员属性同级)
public class LiHuaMao {
}
// 成员方法
public void eat() {
System.out.println("猫吃鱼");
}
}
在同一个类中访问成员内部类
Cat.class
package Demo;
// 外部类
public class Cat {
// 成员属性
private String name = "猫咪";
private int age = 5;
// 内部类(成员内部类,跟成员方法,成员属性同级)
public class LiHuaMao {
private String skill = "抓老鼠";
public void eat() {
System.out.println("小狸花吃老鼠");
}
}
// 成员方法
public void readInnerClass() {
// 在同一个类中访问成员内部类(需要实例化后才能访问)
LiHuaMao liHuaMao = new LiHuaMao();
liHuaMao.eat(); // 小狸花吃老鼠
System.out.println(liHuaMao.skill); // 抓老鼠
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.readInnerClass(); // 小狸花吃老鼠 抓老鼠
}
}
外界访问成员内部类
外界类.成员内部类 xxx = new 外界类().new 成员内部类();
Cat.class
package Demo;
// 外部类
public class Cat {
// 成员属性
private String name = "猫咪";
private int age = 5;
// 内部类(成员内部类,跟成员方法,成员属性同级)
public class LiHuaMao {
private String skill = "抓老鼠";
public void eat() {
System.out.println("小狸花吃老鼠");
}
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat.LiHuaMao liHuaMao = new Cat().new LiHuaMao();
liHuaMao.eat(); // 小狸花吃老鼠
}
}
同一类中访问
Cat.class
package Demo;
// 外部类
public class Cat {
// 成员属性
private String name = "猫咪";
private int age = 5;
// 内部类(静态内部类(我感觉叫静态成员内部类更好理解),跟成员方法,成员属性同级)
public static class LiHuaMao {
private String skill = "抓老鼠";
public void eat() {
System.out.println("小狸花吃老鼠");
}
}
// 非静态成员方法(非静态的可以访问静态)
public void readInnerClass() {
LiHuaMao liHuaMao = new LiHuaMao();
liHuaMao.eat();
}
// 静态成员方法(静态的只能访问静态的)
public static void readInnerClass2() {
LiHuaMao liHuaMao = new LiHuaMao();
liHuaMao.eat();
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.readInnerClass(); // 小狸花吃老鼠
cat.readInnerClass2(); // 小狸花吃老鼠
}
}
外界进行访问
外界类.静态内部类 xxx = new 外界类.静态内部类();
Cat.class
package Demo;
// 外部类
public class Cat {
// 成员属性
private String name = "猫咪";
private static int age = 5;
// 内部类(静态内部类(我感觉叫静态成员内部类更好理解),跟成员方法,成员属性同级)
public static class LiHuaMao {
private String skill = "抓老鼠";
public void showAge() {
// 静态内部类访问外部类,只能访问外部类的静态成员
System.out.println("小狸花今年" + age + "岁了");
}
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat.LiHuaMao liHuaMao = new Cat.LiHuaMao();
liHuaMao.showAge(); // 小狸花今年5岁了
}
}
Cat.class
package Demo;
// 外部类
public class Cat {
// 成员方法
public void type() {
// 内部类(方法内部类,定义在方法内,只能在方法中使用)
class LiHuaMao {
String name = "咪咪";
int age = 5;
void eat() {
System.out.println("吃老鼠");
}
}
LiHuaMao liHuaMao = new LiHuaMao();
System.out.println(liHuaMao.name); // 咪咪
liHuaMao.eat(); // 吃老鼠
}
}
测试类
import Demo.Cat;
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.type(); // 咪咪 吃老鼠
}
}
new Animal() {
// 重写了抽象类Animal的抽象方法
...
}.xxx();
或者
new Animal() {
// 重写了接口Animal的抽象方法
...
}.xxx();
举例:
Animal.class
package Demo;
// 抽象类
public abstract class Animal {
// 抽象方法
public abstract void eat();
}
测试类
import Demo.Animal;
public class Main {
public static void main(String[] args) {
new Animal(){
@Override
public void eat() {
System.out.println("动物都会吃");
}
}.eat(); // 动物都会吃
}
}
思考:正常情况下,接口或者抽象类是无法实例化的,为什么匿名内部类看着却可以实例化抽象类或者接口呢?
其实不是实例化了,而是在编译阶段,内部帮我们实现了子类或者实现类。接口和抽象类是永远不能实例化的!