网站建设是属于虚拟产品吗google网站增加关键词
目录
静态成员
mian方法
多态
抽象类
接口
内部类
成员内部类
静态内部类
方法内部类
匿名内部类
静态成员
- static关键字可以修饰成员方法,成员变量
- 被static修饰的成员,成员变量就变成了静态变量,成员方法就变成了静态方法
- static修饰的特点:被类的所有对象共享访问(只要有一个修改,则用到的都会被修改)
- 访问静态成员,直接 类名. 就可以调用(推荐)。当然也可以通过实例化调用
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}
}
mian方法
- 又叫主方法,是Java虚拟机在调用
public static void main(String[] args) { ... }
- Java虚拟机需要调用类的mian方法,所以改方法,必须使用public修饰(因为Java虚拟机和mian方法不在同一个类中)
- Java虚拟机执行mian方法的时候不需要创建实例化,所以mian方法也必须是static修饰的静态成员方法
- mian方法接收String类型的数组参数,该数组中保存执行Java命令时传递给所执行的类的参数
注意:
- mian方法可以访问本类的静态成员(变量/方法)
- mian方法访问本类中的非静态成员,则需要先创建实例化Mian对象,然后再进行访问
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); // 100Main 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}}
}
多态
多态的前提与体现
- 有继承,实现关系(extends,)
- 存在方法重写
- 有父类引用指向子类对象(左父右子)
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. 存在方法重写@Overridepublic 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 {@Overridepublic void eat() {System.out.println("狗狗吃骨头");}
}
Cat.class
package Demo;public class Cat extends Animal {@Overridepublic 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 {@Overridepublic 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(); // 猫咪会抓老鼠 向下转型后就可以访问了}
}
抽象类
- 在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类
- 抽象类和抽象方法用 abstract 关键字来修饰
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 {@Overridepublic 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 {@Overridepublic 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 {@Overridepublic 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 {@Overridepublic 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关键字注意点(记结论就行,原因不用记)
- abstract 关键字不能与 private 关键字同用,冲突(因为抽象方法必须被子类重写,但是private修饰的方法不能被子类继承)
- abstract 关键字不能与 final 关键字同用,冲突(final修饰的变量,方法都不能被修改,继承)
- abstract 关键字不能与 static 关键字同用,无意义(static是静态的,抽象方法中无方法体,无法调用)
接口
- 接口就是一种公共的规范标准,只要符合规范标准,都可以通用。Java中的接口更多体现在对行为的抽象上
- 接口,用 interface 修饰
public interface 接口名 { }
- 类实现接口用 implements 表示
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 abstractvoid drink();public default void run() {System.out.println("动物都会奔跑");}
}
Cat.class
package Demo;public class Cat implements Animal{@Overridepublic void eat() {System.out.println("猫吃鱼");}@Overridepublic 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 abstractvoid drink();public default void run() {System.out.println("动物都会奔跑");}
}
Cat.class
package Demo;public class Cat implements Animal{@Overridepublic void eat() {System.out.println("猫吃鱼");}@Overridepublic 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(); // 猫吃鱼(多态访问成员方法规则:编译看左,执行看右。所以输出的是猫的吃方法)}
}
- 接口中不能有构造方法
- 接口的实现类,要不重写接口中所有的抽象方法,要不就是抽象类。但是最终只要使用接口,还是要重写所有的抽象方法。同抽象类
- 定义了一个类,如果没有继承任何父类,则在默认情况下,就继承了Object父类,任何类的祖宗类,都是Object类
类与接口的小区别
- 一个类只能单继承一个父类。但是接口可以继承n个不同的接口
- 一个类可以实现n个接口
内部类
- 就是在一个类中又定义了一个类
比如:在一个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(); // 小狸花吃老鼠}
}
静态内部类
- 定义在外部类中的成员方法外,并由static修饰的内部类(其实就是用static修饰成员内部类)
同一类中访问
- 外部类中的静态成员方法,只能访问静态内部类
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(){@Overridepublic void eat() {System.out.println("动物都会吃");}}.eat(); // 动物都会吃}
}
- 接口同理
思考:正常情况下,接口或者抽象类是无法实例化的,为什么匿名内部类看着却可以实例化抽象类或者接口呢?
其实不是实例化了,而是在编译阶段,内部帮我们实现了子类或者实现类。接口和抽象类是永远不能实例化的!
- 使用匿名内部类,就不需要创建实现类或者子类了,简化了步骤,底层帮我们创建了子类