目的
学习关于:
1.定义和使用内部类
2.内部类和外部类之间的调用规则
3.子类对父类有访问权限的方法的重写和使用
4.几种代码块的使用范围和执行顺序以及区别
5.多态的优点和用法
6.java继承的规则和使用
技术及其方法
1.内部类
成员内部类:定义在另一个类的内部的类,是最普通的内部类
class Outter{
public int a;
public int b;
public Outter(int a,int b){
this.a = a;
this.b= b
}
class Inner{
public void DrawInner(){
System.out.println("i'm Inner");
}
}
}
这样看起来,类Inner像是类Outter的一个成员,Outter称为外部类。成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
注意:当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:
class Outter{
public int a;
public int b;
public Outter(int a,int b){
this.a = a;
this.b= b
getDrawInnnerInstance.DrawInner();
}
public DrawInner getDarwInnerInstance(){
return new DrawInner();
}
class Inner{
public void DrawInner(){
System.out.println("i'm Inner");
}
}
}
虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:
class Circle {
private double radius = 0;
public Circle(double radius) {
this.radius = radius;
getDrawInstance().drawSahpe(); //必须先创建成员内部类的对象,再进行访问
}
private Draw getDrawInstance() {
return new Draw();
}
class Draw { //内部类
public void drawSahpe() {
System.out.println(radius); //外部类的private成员
}
}
}
成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。创建成员内部类对象的一般方式如下:
public class Test {
public static void main(String[] args) {
//第一种方式:
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner(); //必须通过Outter对象来创建
//第二种方式:
Outter.Inner inner1 = outter.getInnerInstance();
}
}
class Outter {
private Inner inner = null;
public Outter() {
}
public Inner getInnerInstance() {
if(inner == null)
inner = new Inner();
return inner;
}
class Inner {
public Inner() {
}
}
}
内部类可以拥有 private 访问权限、protected 访问权限、public 访问权限及包访问权限。比如上面的例子,如果成员内部类 Inner 用 private 修饰,则只能在外部类的内部访问,如果用 public 修饰,则任何地方都能访问;如果用 protected 修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被 public 和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。
2.重写
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写。重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
}
}
以上实例编译运行结果如下:
动物可以移动
狗可以跑和走
方法的重写规则:
1.参数列表必须完全与被重写方法的相同。
2.返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
3.访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
4.父类的成员方法只能被它的子类重写。
5.声明为 final 的方法不能被重写。
6.声明为 static 的方法不能被重写,但是能够被再次声明。
7.子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
8.子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
9.重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
10.构造方法不能被重写。
11.如果不能继承一个方法,则不能重写这个方法。
Super 关键字的使用
当需要在子类中调用父类的被重写方法时,要使用 super 关键字。
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
super.move(); // 应用super类的方法
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal b = new Dog(); // Dog 对象
b.move(); //执行 Dog类的方法
}
}
以上实例编译运行结果如下:
动物可以移动
狗可以跑和走
3.代码块
一.静态代码块:在java类中(方法中不能存在静态代码块)使用static关键字和{}声明的代码块:
public class CodeBlock {
static{
System.out.println("静态代码块");
}
}
1.静态代码块在类被加载的时候就运行了,而且只运行一次,并且优先于各种代码块以及构造函数
2.一般情况下,如果有些代码需要在项目启动的时候就执行,这时候就需要静态代码块。
3.静态代码块不能存在任何方法体中
4.静态代码块不能访问普通变量
二.构造代码块:在java类中使用{}声明的代码块(和静态代码块的区别是少了static关键字):
public class CodeBlock {
static{
System.out.println("静态代码块");
}
{
System.out.println("构造代码块");
}
}
1.构造代码块在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造函数执行。
4.多态
1.多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。
2.多态存在的三个必要条件
1.继承
2.重写
3.父类引用指向子类对象
比如:
Parent p = new Child();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
Test.java 文件代码:
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
执行以上程序,输出结果为:
吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠
5.继承
承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
//类的继承格式
class 父类 {
}
class 子类 extends 父类 {
}
注意: Java 不支持多继承,但支持多重继承。
1.子类拥有父类非 private 的属性、方法。
2.子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
3.子类可以用自己的方式实现父类的方法。
4.Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
5.提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
实际使用
class Person{
String name;
int age;
public void walk(){
System.out.println("Person walking...");
}
public void eat(){
System.out.println("Person eating...");
}
}
class CivilServant extends Person{
public CivilServant(String name,int age,int salary,int magazinenumber){
this.name =name;
this.age =age;
this.salary =salary;
this.magazinenumber =magazinenumber;
}
int salary;
int magazinenumber;
public void show(){
System.out.println(" name: "+name+" age: "+age+" salary: "+salary+" magazinenumber: "+magazinenumber);
}
}
class Clerk extends Person{
public Clerk(String name,int age,int salary,String tec){
this.name =name;
this.age = age;
this.salary =salary;
this.tec = tec;
}
int salary;
String tec;
public void show(){
System.out.println(" name: "+name+" age: "+age +" salary: "+salary+" tec: "+ tec);
}
}
class TestMyDemo{
public static void main(String[] args){
String[] tecs = new String[]{"computer","ps","pr","au"};
Person person1=new CivilServant("joy",17,2000,5);
Person person2 =new CivilServant("envy",18,3000,7);
Person person3 = new Clerk("sad",20,4000,"ps");
Person person4 = new Clerk("scare",21,9000,"pr");
ArrayList<Person> people = new ArrayList<>();
people.add(person1);
people.add(person2);
people.add(person3);
people.add(person4);
((CivilServant) person1).show();
((CivilServant) person2).show();
((Clerk) person3).show();
((Clerk) person4).show();
}