1. 方法
1.1 注意事项
- 方法不能嵌套定义
- 对于void类型方法,return可以不写 或着 只写一个return
1.2 通用格式
public static 返回值类型 方法名():{方法体;return 返回值;}
1.3 方法重载
多个方法在同一个类中
多个方法具有相同的方法名
多个方法的参数不相同,类型不同或者数量不同
注意与返回值无关
2. 内部类
- 内部类方法可以访问该类定义所在的作用域中的数据 , 包括私有的数据
- 内部类可以对同一个包中的其他类隐藏起来
- 当想要定义一个回调函数且不想编写大量代码时 , 使用匿名( anonymous ) 内部类比较便捷
2.0 权限修饰符
| 修饰符 | 同一个类中 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 |
|---|---|---|---|---|
| private | √ | |||
| default | √ | √ | ||
| protected | √ | √ | √ | |
| public | √ | √ | √ | √ |
2.1 非静态内部类
非静态内部类中不允许存在静态成员
public class OutClass {String vars = "外部类变量";class InClass{String vars = "内部类变量";void method(){String vars = "局部变量";System.out.println(vars); // 局部变量System.out.println(this.vars); // 内部类变量System.out.println(MytestDemo.this.vars); // 外部类变量}}// 调用内部类的方法,不能在静态main中直接调用非静态内部类public void test(){InClass ic = new InClass(); // 外部类调用内部类的变量,要先创建内部类对象System.out.println("外部类调用内部类的变量:"+ ic.vars); // 外部类调用内部类的变量:内部类变量ic.method();}public static void main(String[] args) {// new OutClass().new InClass().method(); // 先创建外部类再创建内部类也可以使用new OutClass().test(); // 非静态内部类调用}}
2.2 静态内部类
static关键字的作用是把类的成员变成类相关,而不是实例相关,即static修饰的成员属于整个类,而不属于单个对象。外部类的上一级程序单元是包,所以不可使用static修饰;而内部类的上一级程序单元是外部类,使用static修饰可以将内部类变成外部类相关,而不是外部类实例相关。因此static关键字不可修饰外部类,但可修饰内部类
- 静态内部类可以包含静态成员,也可以包含非静态成员
- 静态成员不能访问非静态成员
- 非静态成员不能访问外部非静态成员
public class OutClass{private static String str = "静态外部变量";private String str1 = "非静态外部变量"; // 静态内部类无法访问static class StaticInClass{static String istr = "静态内部变量";String istr1 = "非静态内部变量";void method(){ // 非静态成员可以访问:(除外部非静态变量)System.out.println(istr); // 静态内部变量System.out.println(istr1); // 非静态内部变量System.out.println(str); // 静态外部变量// System.out.println(str1);}static void staticMethod(){ // 静态成员可以访问:静态变量System.out.println(istr); // 内部静态变量// System.out.println(istr1);System.out.println(str); // 外部静态变量// System.out.println(str1);}}public static void main(String[] args) {new StaticInClass().method(); // 直接创建静态内部类对象,因为static将内部类变成了外部类相关new StaticInClass().staticMethod(); // 使用静态内部类的静态方法System.out.println(StaticInClass.istr); // 外部类调用静态内部类的静态内部成员// System.out.println(StaticInClass.istr1); 不能直接使用非静态内部变量System.out.println(new StaticInClass().istr1); // 可以通过创建对象调用非静态内部类}}
2.3 局部内部类
定义在方法内的类
2.4 匿名内部类
new 接口() | 父类构造器(){类体}
// 存在一个没有实现的接口public interface Product {double getPrice();String getName();}// 正常需要通过创建一个类实现该接口的功能class ProductInfo implements Product{public double getPrice(){ return 100.001; }public String getName(){ return "Peter"; }}// 但是通过匿名内部类则省略了实现该接口的类public class AnoymousTest {public void test(Product p){System.out.println(p.getName() + " spend "+p.getPrice());}public static void main(String[] args) {AnoymousTest at = new AnoymousTest();// at.test( new ProductInfo() ); 内部类更改了这一步at.test(new Product() {@Overridepublic double getPrice() {return 10.001;}@Overridepublic String getName() {return "peter";}});}}
// 存在一个没有实现的抽象类abstract class Product {public abstract double getPrice(); // 需要重写抽象方法private String name;public Product(){}public Product(String name){this.name = name;} // 构造器public String getName() { return name; }}public class AnoymousTest {public void test(Product p){System.out.println(p.getName() + " spend "+p.getPrice());}public static void main(String[] args) {int localVar = 10; // 局部变量AnoymousTest at = new AnoymousTest();at.test(new Product("Peter") { // 通过带参构造器创建{System.out.println(age);// 当使用了局部变量后,相当于系统自动改为final int localVar = 10;// age = 20; 报错,提示final变量不可变}@Overridepublic double getPrice() { // 重写方法return 100.1;}});}}
匿名内部类可以访问局部变量,当访问时相当于自动加了final修饰,此时不可以对该变量进行任何修改。
3. 多态
3.1 向上向下转型
定义一个父类Animals包含eat()方法、age初始值为0
然后再定义两个子类:Dog和Cat,都重写了eat()方法和age,然后再分别有自己的特有方法狗咆叫bark(),猫睡觉sleep()
向上转型:Animals a = new Cat()
向下转型:Cat cat = (Cat) a,必须要先经过向上转型的变量—再向下转型,此时cat就拥有子类自己定义的特有方法cat.sleep()
instanceof用法:a instanceof Cat 这里a必须是经过向上转型后的父类对象,而Cat是继承父类的子类
// 父类public class Animals {public int age = 0;public void eat(){System.out.println("Eat...");}}// 子类 继承 父类 Animalspublic class Dog extends Animals {public int age = 10;@Overridepublic void eat(){System.out.println("eat bone...");}public void bark(){System.out.println("dog bark...");}}public class Cat extends Animals{public int age = 2;@Overridepublic void eat(){System.out.println("eat fish...");}public void sleep(){System.out.println("cat sleep...");}}
有一个宠物店AnimalsShop将宠物放入后,统计个数,以及可以取出该宠物
public class AnimalsShop {// 注意这里用的Animals泛型,加入宠物时,不关心宠物的具体类型private List<Animals> list = new ArrayList<Animals>();// 当加入一个宠物时,相当于进行了向上转型public void add(Animals a){list.add(a);}public int getSize(){return list.size();}// 取出的宠物也是经过向上转型的,此时类型为Animalspublic Animals getAnimal(int position){return list.get(position);}}
public static final int DOG = 0;public static final int CAT = 1;@Testpublic void test4(){// 通过泛型进行向上转型将不同类型的动物加入集合,此时不需要动物的不同特性,只需要知道个数即可AnimalsShop as = new AnimalsShop();as.add(new Dog());as.add(new Cat());// 获取动物个数System.out.println(as.getSize());// 查看所有的宠物Dog dog = (Dog) as.getAnimal(DOG); // 直接向下转型,并不安全,因为可以编译通过但运行出错dog.eat();dog.bark();Animals a = as.getAnimal(CAT); // 获取已经向上转型CatSystem.out.println(a instanceof Dog); // false,向上转型的Cat和Dog不构成子类关系// ((已经经过向上转型的)父类对象 instanceof 子类 ) 来判断是否可以向下转型更安全,防止ClassCastException转换异常if(a instanceof Cat){Cat cat = (Cat) as.getAnimal(CAT);cat.eat();cat.sleep();}}
向下转型的最大好处是:java的泛型编程,用处很大,Java的集合类都是这样的。
参考博客
3.2 多态的特点
多态的前提:
- 存在继承或实现接口
extend或implement - 重写方法
@Override - 父类引用指向子类对象
Animals a = new Cat()
多态的特点:
- 相同变量看父类
a.age = 0 - 重写方法看子类
eat()看子类 - 子类特有方法不可用
a.sleep()不可用
public static void animalEat(Animals a){a.eat();}@Testpublic void test3(){Animals a1 = new Dog();System.out.println(a1.age); // 1. 变量看父类a1.eat(); // 2. 方法看子类// a1.bark(); 3. 子类特有不可用Animals a2 = new Cat();a2.eat();// 当向上转型后,通过一个通用方法调用不同的子类,即可实现子类的方法animalEat(new Dog());animalEat(new Cat());}
