1. 方法

1.1 注意事项

  • 方法不能嵌套定义
  • 对于void类型方法,return可以不写 或着 只写一个return

1.2 通用格式

  1. public static 返回值类型 方法名():{
  2. 方法体;
  3. return 返回值;
  4. }

1.3 方法重载

  • 多个方法在同一个类

  • 多个方法具有相同的方法名

  • 多个方法的参数不相同,类型不同或者数量不同

  • 注意与返回值无关

2. 内部类

  • 内部类方法可以访问该类定义所在的作用域中的数据 , 包括私有的数据
  • 内部类可以对同一个包中的其他类隐藏起来
  • 当想要定义一个回调函数且不想编写大量代码时 , 使用匿名( anonymous ) 内部类比较便捷

2.0 权限修饰符

修饰符 同一个类中 同一个包中子类无关类 不同包的子类 不同包的无关类
private
default
protected
public

2.1 非静态内部类

非静态内部类中不允许存在静态成员

  1. public class OutClass {
  2. String vars = "外部类变量";
  3. class InClass{
  4. String vars = "内部类变量";
  5. void method(){
  6. String vars = "局部变量";
  7. System.out.println(vars); // 局部变量
  8. System.out.println(this.vars); // 内部类变量
  9. System.out.println(MytestDemo.this.vars); // 外部类变量
  10. }
  11. }
  12. // 调用内部类的方法,不能在静态main中直接调用非静态内部类
  13. public void test(){
  14. InClass ic = new InClass(); // 外部类调用内部类的变量,要先创建内部类对象
  15. System.out.println("外部类调用内部类的变量:"+ ic.vars); // 外部类调用内部类的变量:内部类变量
  16. ic.method();
  17. }
  18. public static void main(String[] args) {
  19. // new OutClass().new InClass().method(); // 先创建外部类再创建内部类也可以使用
  20. new OutClass().test(); // 非静态内部类调用
  21. }
  22. }

2.2 静态内部类

static关键字的作用是把类的成员变成类相关,而不是实例相关,即static修饰的成员属于整个类,而不属于单个对象。外部类的上一级程序单元是包,所以不可使用static修饰;而内部类的上一级程序单元是外部类,使用static修饰可以将内部类变成外部类相关,而不是外部类实例相关。因此static关键字不可修饰外部类,但可修饰内部类

  • 静态内部类可以包含静态成员,也可以包含非静态成员
  • 静态成员不能访问非静态成员
  • 非静态成员不能访问外部非静态成员
  1. public class OutClass{
  2. private static String str = "静态外部变量";
  3. private String str1 = "非静态外部变量"; // 静态内部类无法访问
  4. static class StaticInClass{
  5. static String istr = "静态内部变量";
  6. String istr1 = "非静态内部变量";
  7. void method(){ // 非静态成员可以访问:(除外部非静态变量)
  8. System.out.println(istr); // 静态内部变量
  9. System.out.println(istr1); // 非静态内部变量
  10. System.out.println(str); // 静态外部变量
  11. // System.out.println(str1);
  12. }
  13. static void staticMethod(){ // 静态成员可以访问:静态变量
  14. System.out.println(istr); // 内部静态变量
  15. // System.out.println(istr1);
  16. System.out.println(str); // 外部静态变量
  17. // System.out.println(str1);
  18. }
  19. }
  20. public static void main(String[] args) {
  21. new StaticInClass().method(); // 直接创建静态内部类对象,因为static将内部类变成了外部类相关
  22. new StaticInClass().staticMethod(); // 使用静态内部类的静态方法
  23. System.out.println(StaticInClass.istr); // 外部类调用静态内部类的静态内部成员
  24. // System.out.println(StaticInClass.istr1); 不能直接使用非静态内部变量
  25. System.out.println(new StaticInClass().istr1); // 可以通过创建对象调用非静态内部类
  26. }
  27. }

2.3 局部内部类

定义在方法内的类

2.4 匿名内部类

  1. new 接口() | 父类构造器(){
  2. 类体
  3. }
  1. // 存在一个没有实现的接口
  2. public interface Product {
  3. double getPrice();
  4. String getName();
  5. }
  6. // 正常需要通过创建一个类实现该接口的功能
  7. class ProductInfo implements Product{
  8. public double getPrice(){ return 100.001; }
  9. public String getName(){ return "Peter"; }
  10. }
  11. // 但是通过匿名内部类则省略了实现该接口的类
  12. public class AnoymousTest {
  13. public void test(Product p){
  14. System.out.println(p.getName() + " spend "+p.getPrice());
  15. }
  16. public static void main(String[] args) {
  17. AnoymousTest at = new AnoymousTest();
  18. // at.test( new ProductInfo() ); 内部类更改了这一步
  19. at.test(new Product() {
  20. @Override
  21. public double getPrice() {
  22. return 10.001;
  23. }
  24. @Override
  25. public String getName() {
  26. return "peter";
  27. }
  28. });
  29. }
  30. }
  1. // 存在一个没有实现的抽象类
  2. abstract class Product {
  3. public abstract double getPrice(); // 需要重写抽象方法
  4. private String name;
  5. public Product(){}
  6. public Product(String name){this.name = name;} // 构造器
  7. public String getName() { return name; }
  8. }
  9. public class AnoymousTest {
  10. public void test(Product p){
  11. System.out.println(p.getName() + " spend "+p.getPrice());
  12. }
  13. public static void main(String[] args) {
  14. int localVar = 10; // 局部变量
  15. AnoymousTest at = new AnoymousTest();
  16. at.test(new Product("Peter") { // 通过带参构造器创建
  17. {
  18. System.out.println(age);
  19. // 当使用了局部变量后,相当于系统自动改为final int localVar = 10;
  20. // age = 20; 报错,提示final变量不可变
  21. }
  22. @Override
  23. public double getPrice() { // 重写方法
  24. return 100.1;
  25. }
  26. });
  27. }
  28. }

匿名内部类可以访问局部变量,当访问时相当于自动加了final修饰,此时不可以对该变量进行任何修改。

3. 多态

3.1 向上向下转型

定义一个父类Animals包含eat()方法、age初始值为0

然后再定义两个子类:DogCat,都重写了eat()方法和age,然后再分别有自己的特有方法狗咆叫bark(),猫睡觉sleep()

向上转型:Animals a = new Cat()

向下转型:Cat cat = (Cat) a,必须要先经过向上转型的变量—再向下转型,此时cat就拥有子类自己定义的特有方法cat.sleep()

instanceof用法:a instanceof Cat 这里a必须是经过向上转型后的父类对象,而Cat是继承父类的子类

  1. // 父类
  2. public class Animals {
  3. public int age = 0;
  4. public void eat(){
  5. System.out.println("Eat...");
  6. }
  7. }
  8. // 子类 继承 父类 Animals
  9. public class Dog extends Animals {
  10. public int age = 10;
  11. @Override
  12. public void eat(){
  13. System.out.println("eat bone...");
  14. }
  15. public void bark(){
  16. System.out.println("dog bark...");
  17. }
  18. }
  19. public class Cat extends Animals{
  20. public int age = 2;
  21. @Override
  22. public void eat(){
  23. System.out.println("eat fish...");
  24. }
  25. public void sleep(){
  26. System.out.println("cat sleep...");
  27. }
  28. }

有一个宠物店AnimalsShop将宠物放入后,统计个数,以及可以取出该宠物

  1. public class AnimalsShop {
  2. // 注意这里用的Animals泛型,加入宠物时,不关心宠物的具体类型
  3. private List<Animals> list = new ArrayList<Animals>();
  4. // 当加入一个宠物时,相当于进行了向上转型
  5. public void add(Animals a){
  6. list.add(a);
  7. }
  8. public int getSize(){
  9. return list.size();
  10. }
  11. // 取出的宠物也是经过向上转型的,此时类型为Animals
  12. public Animals getAnimal(int position){
  13. return list.get(position);
  14. }
  15. }
  1. public static final int DOG = 0;
  2. public static final int CAT = 1;
  3. @Test
  4. public void test4(){
  5. // 通过泛型进行向上转型将不同类型的动物加入集合,此时不需要动物的不同特性,只需要知道个数即可
  6. AnimalsShop as = new AnimalsShop();
  7. as.add(new Dog());
  8. as.add(new Cat());
  9. // 获取动物个数
  10. System.out.println(as.getSize());
  11. // 查看所有的宠物
  12. Dog dog = (Dog) as.getAnimal(DOG); // 直接向下转型,并不安全,因为可以编译通过但运行出错
  13. dog.eat();
  14. dog.bark();
  15. Animals a = as.getAnimal(CAT); // 获取已经向上转型Cat
  16. System.out.println(a instanceof Dog); // false,向上转型的Cat和Dog不构成子类关系
  17. // ((已经经过向上转型的)父类对象 instanceof 子类 ) 来判断是否可以向下转型更安全,防止ClassCastException转换异常
  18. if(a instanceof Cat){
  19. Cat cat = (Cat) as.getAnimal(CAT);
  20. cat.eat();
  21. cat.sleep();
  22. }
  23. }

向下转型的最大好处是:java的泛型编程,用处很大,Java的集合类都是这样的。
参考博客

Java向下转型的意义

Java对象类型向上转型

3.2 多态的特点

多态的前提:

  • 存在继承或实现接口extendimplement
  • 重写方法@Override
  • 父类引用指向子类对象Animals a = new Cat()

多态的特点:

  • 相同变量看父类a.age = 0
  • 重写方法看子类eat()看子类
  • 子类特有方法不可用a.sleep()不可用
  1. public static void animalEat(Animals a){
  2. a.eat();
  3. }
  4. @Test
  5. public void test3(){
  6. Animals a1 = new Dog();
  7. System.out.println(a1.age); // 1. 变量看父类
  8. a1.eat(); // 2. 方法看子类
  9. // a1.bark(); 3. 子类特有不可用
  10. Animals a2 = new Cat();
  11. a2.eat();
  12. // 当向上转型后,通过一个通用方法调用不同的子类,即可实现子类的方法
  13. animalEat(new Dog());
  14. animalEat(new Cat());
  15. }