Java(4):基础:面向对象学习的重要点

本文深入讲解了Java中的关键概念,包括成员变量与局部变量的区别、内部类的使用、抽象类与接口的比较、多态的注意事项及封装的重要性。

日期:2017/10/12

一、成员变量和局部变量的区别:

A:在类中的位置不同

成员变量 类中方法外
局部变量 方法内或者方法声明上

B:在内存中的位置不同

成员变量 堆内存
局部变量 栈内存

C:生命周期不同

全局成员变量 随着对象的存在而存在,随着对象的消失而消失
局部变量 随着方法的调用而存在,随着方法的调用完毕而消失

D:初始化值不同

成员变量 有默认的初始化值
局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。

注意:
如果有同名的变量,一般会采用就近原则。


二、内部类的使用

      在一个类的内部定义了一个类(内部类+外部类),这种情况下,内部类可以看做外部类的一个成员。

      4种:静态内部类,成员内部类,局部内部类,匿名内部类。

     内部类例子:

package com.innerclass;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.sound.midi.SysexMessage;

class outerClass1{
	static class innerClass{}    //静态内部类
}
class outerClass2{
	class innerClass{}             // 成员内部类(普通内部类)
}
class outerClass3{
	public void memberFuntion(){
		class innerClass {}         //局部内部类
	}
}
/*匿名内部类
 * 

class MyFrame extends Frame{		//外部类
	public MyFrame{
		addWindowListener(new WindowAdapter(){		//匿名内部类WindowAdapter
			public void windowClosing(WindowEvent e){
				dispose();
				System.exit(0);
				}
			private void dispose() {}
		});		
}

*/



三、抽象和接口的比较

      3.1 接口:Java只支持单继承(一个类只能有一个父类)。因此,引入接口的概念(接口可以多继承,一个类可以实现多个接口)。

                接口是抽象方法定义的集合(接口 interface 里面都是抽象 abstract 方法),特殊的抽象类       

(1)有些时候,不是事物本身具备的功能,我们就考虑使用接口来扩展。
(2)接口的特点:
A:定义接口用关键字interface
格式是:interface 接口名 {}
B:类实现接口用关键字implements 
格式是:class 类名 implements 接口名 {}
C:接口不能实例化
D:接口的子类
a:要么是抽象类
b:要么重写接口中的所有方法
(3)接口的成员特点
A:成员变量
只能是常量。
默认修饰符:public static final
B:成员方法
只能是抽象方法。
默认修饰符:public abstract 
推荐:
建议自己写接口的时候,把默认修饰符加上。
(4)类与接口的关系
A:类与类
继承关系,只能单继承,可以多层继承。
B:类与接口
实现关系,可以单实现,也可以多实现。
还可以在继承一个类的同时实现多个接口。
C:接口与接口
继承关系,可以单继承,也可以多继承。
(5)抽象类和接口的区别?
A:成员区别
B:关系区别
C:设计理念区别
抽象类:父抽象类,里面定义的是共性内容。
接口:父接口,里面定义的是扩展内容。

(6)接口可以作为类型参数作为传递。


  • 接口不能用于实例化对象。
  • 接口没有构造方法。
  • 接口中所有的方法必须是抽象方法。
  • 接口不能包含成员变量,除了 static 和 final 变量。
  • 接口不是被类继承了,而是要被类实现。
  • 接口支持多继承。

下面是接口的小例子(1):

package com.interfaceTest;
import java.util.ArrayList;
interface Stuff{}
//矿石
interface Ore extends Stuff{}
//武器
interface Weapon extends Stuff{}
//垃圾
interface Rubbish extends Stuff{}
//金矿
class Gold implements Ore{
	public String toString(){
		return "Gold";
	}
}
//铜矿
class Copper implements Ore{
	public String toString(){
		return "Copper";
	}
}
//枪
class Gun implements Weapon{
	public String toString(){
		return "Gun";
	}
}
//榴弹
class Grenade implements Weapon{
	public String toString(){
		return "Grenade";
	}
}
//石头
class Stone implements Rubbish{
	public String toString(){
		return "Stone";
	}
}

public class Test {
	public static ArrayList<Stuff> collectStuff(Stuff[] s){
		ArrayList<Stuff> al = new ArrayList<Stuff>();
		for(int i = 0;i < s.length; i++){
			if(! (s[i] instanceof Rubbish))
				//ArrayList.add()
				al.add(s[i]); 
		}
		return al;
	}

	public static void main(String[] args) {
		Stuff[] s = {new Gold(),new Copper(),new Gun(),new Grenade(),new Stone()};
		ArrayList<Stuff> al = collectStuff(s);
		System.out.println("The useful stuff collection are: ");
		for(int i = 0;i < al.size();i++){
			System.out.println(al.get(i));
			System.out.println("*"+al.get(i).getClass());
		}
	}

}

小例子(2):

package com.interfaceTest;

//接口,定义了一个方法
interface IntCompare{
	public int cmp(int a,int b);
}

class Cmp1 implements IntCompare{
	public int cmp(int a,int b){
		if (a > b){
			return 1;
		}else if (a < b){
			return -1;
		}else {
			return 0;
		}
	}
}

class Cmp2 implements IntCompare{
	public int cmp(int a,int b){
		if (a > b){
			return -1;
		}else if(a <b ){
			return 1;
		}else{
			return 0;
		}
	}
}

public class TestTwo {
	public static void insertSort(int [] a,IntCompare cmp){
		if (a != null){
			for (int i  = 1;i<a.length;i++){
				int temp = a[i],j = i;
				if (cmp.cmp(a[j -1], temp) == 1){
					while(j >= 1 && cmp.cmp(a[j-1], temp) == 1){
						a[j] = a[j - 1];
						j--;
					}
				}
				a[j] = temp;
			}
		}
	}

	public static void main(String[] args) {
		int [] array1 = {7,6,8,55,11,2,3,9};
		insertSort(array1, new Cmp1());
		System.out.println("升序排列: ");
		for (int i = 0;i< array1.length;i++)
			System.out.print(array1[i]+" ");
		System.out.println();
		int [] array2 = {8 ,6,2,55,44,11,3,2};
		insertSort(array2, new Cmp2());
		System.out.println("降序排列: ");
		for (int i = 0;i< array2.length;i++)
			System.out.print(array2[i]+" ");
	}

}

      3.2 抽象:

      (1)有些时候,我们对事物不能用具体的东西来描述,这个时候就应该把事物定义为抽象类
      (2)抽象类的特点:
      A:抽象类或者抽象方法必须用abstract修饰
      B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
      C:抽象类不能实例化
            可以按照多态的方式实例化。
      D:抽象类的子类
            a:要么是抽象类
            b:要么重写抽象类中的所有抽象方法
      (3)抽象类的成员特点:
      A:成员变量
            可以是变量,也可以是常量
      B:构造方法
            有。
            不能实例化,有构造方法有什么意义呢?
                  用于子类访问父类数据的初始化。
      C:成员方法
            可以是抽象的,也可以是非抽象


        在使用抽象类时需要注意几点:

        1、抽象类不能被实例化,实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。

        2、抽象方法必须由子类来进行重写。

        3、只要包含一个抽象方法的抽象类,该方法必须要定义成抽象类,不管是否还包含有其他方法。

        4、抽象类中可以包含具体的方法,当然也可以不包含抽象方法。

        5、子类中的抽象方法不能与父类的抽象方法同名。

        6、abstract 不能与 final 并列修饰同一个类。

        7、abstract 不能与 private、static、final 或 native 并列修饰同一个方法。


四、多态使用的注意点

同一类型的变量,调用了同样的方法,产生了不同的结果,称之为“多态”。

1、父类类型的变量 指向 子类的对象,调用父类的被重写的方法时,会执行子类重写的方法;

2、在多态的情况下(父类类型的变量 指向 子类的对象),不能调用子类新增的方法;

public class Test{ 
	           public void method(Person e) {	 //设Person类中没有getschool()方法
		      System.out.pritnln(e.getschool());   //非法,编译时错误
		 
		      if(e  instanceof  Student){
		          Student me = (Student)e;	//将e强制转换为Student类型
		          System.out.pritnln(me.getschool());
		      }	    
	           }

	           public static  void main(Stirng args[]){
	              Test t = new Test();
	               Student m = new Student();
	               t.method(m);
	           }
}

3、在多态的情况下(父类类型的变量 指向 子类的对象),可以对 对象 进行 强制类型转换;

      3.1 父类的对象可以转化为任何子类的类型,但可能发生错误;

      3.2 只有在父子关系的情况,方可进行 强制类型转换;

	Person p = new Student();
	Object o = new Person();//Object类型的变量o,指向Person类型的对象
	o = new Student(); //Object类型的变量o,指向Student类型的对象

4、声明为父类的类型变量,但指向了子类的对象,所以实际引用了子类对象,那么就不能访问子类添加的方法和属性;(这也解释了为啥不能调用子类 新增 的方法

	Student m = new Student();
	m.school = “pku”; 	//合法,Student类有school成员变量
	Person e = new Student(); 
	e.school = “pku”;	//非法,Person类没有school成员变量

5、方法声明的形参类型为父类类型,可以使用 子类的对象 作为  实参 调用该方法。

public class Test{ 
	public void method(Person e) {
	           //……
	           e.getInfo();
	}
	public static  void main(Stirng args[]){
	           Test t = new Test();
	            Student m = new Student();
	            t.method(m); //子类的对象m传送给父类类型的参数e
	}
}

PS:instanceof 操作符

              x instanceof A:检验x是否为类A的对象,返回值为boolean型.要求x所属的类与类A必须是子类和父类的关系,否则编译错误。如果x属于类A的子类B,x instanceof A值也为true。

public class Person extends Object {…}
public class Student extends Person {…}
public class Graduate extends Person {…}
//-------------------------------------------------------------------
public void method1(Person e) {
	if (e instanceof Person) 
		// 处理Person类及其子类对象
	if (e instanceof Student) 
		//处理Student类及其子类对象
	if (e instanceof Graduate)
		//处理Graduate类及其子类对象
}


五、封装

        封装是指:将客观事物抽象成类,每个类对各自的数据和方法实行保护。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后台技术汇

对你的帮助,是对我的最好鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值