JAVA基础面向对象

一、方法的演示

1.前言

/**
 * 方法的演示
 * 方法::也称函数,或者叫过程
 * 1.用于封装一段特定的逻辑功能
 * 2.尽可能的独立,只干一件事
 * 3.优点
 *    3)可以被调用多次(避免代码重复、结构清晰)
 *    4)结构清晰、便于维护( 便于维护、便于合作开发)
 *    
 * 方法的定义:
 *   修饰词 返回值类型 方法名(参数列表){ 方法体   }
 * 注意:
 * 		1)方法可以有参也可以无参,有参更灵活
 *		2)方法可以有返回值也可以没有返回值: 无返回值,返回值类型写void
 *		               					有返回值,返回值类型写具体的数据类型
 *										(java语法规定,方法在声明时必须指定返回值类型)
 *		3)方法体中return:return语句的作用在于结束方法且将数据返回给调用方。
 *						  有返回值:1.结束方法的执行  2.返回结果给调用方
 *								  return后的表达式类型必须与方法定义的返回类型匹配
 *						  无返回值:return;1.结束方法的执行
 *
 *何时有返回值?何时没有返回值?
 *规律: 
 *若方法执行完后,方法外面需要该方法中的某个数,就有返回值
 *若方法执行完后,方法外面不需要该方法中的某个数,就没有返回值  
 * 
 */

2.方法的演示


public class MethodDemo {
	public static void main(String[] args) {
		/**
		* 方法的调用
      	*	无返回值方法:  方法名(有参传参);
      	*	有返回值方法:  数据类型 变量 = 方法名(有参传参);
        *                 方法名(有参传参);------几乎不用
		*/
		/*
		 * 无参方法调用:方法名();
		 */
		say();
		/*
		 * 有参五返回值方法调用:必须传参数,参数类型必须匹配:方法名(有参传参);
		 */		
		//sayHi(); //编译错误,必须传参数
		//sayHi(8); //编译错误,参数类型不匹配		
		sayHi("zhangsan"); //String name="zhangsan"
		sayHi("lisi"); //String name="lisi"
		sayHi("wangwu"); //String name="wangwu"
		/*
		 * 无参有返回值方法调用: 数据类型 变量 = 方法名();
		 */
		int num = getNum();
		System.out.println(num); //88
		/*
		 * 有参有返回值方法调用: 数据类型 变量 = 方法名(有参传参);
		 */
		double d = plus(5,6); //double num1=5,double num2=6
		System.out.println(d); //11
		double a = 5.5;
		double b = 4.4;
		double dou = plus(a,b); //double num1=5.5,double num2=4.4
		System.out.println(dou);		
		a(); //方法的嵌套调用		
		System.out.println("over");
	}	
	/*
	 * 方法的嵌套:方法中调方法
	 */
	public static void a(){
		System.out.println(111);
		b();//方法的嵌套调用
		System.out.println(222);
	}
	public static void b(){
		System.out.println(333);
		
	}
	//有参有返回值
	public static double plus(double num1,double num2){
		//double num = num1+num2;
		//return num; //返回的不是num,而是num里面那个数
		return num1+num2; //返回的是num1+num2的值
	}
	
	//无参有返回值
	public static int getNum(){
		//return; //编译错误,必须返回一个值
		//return 5.55; //编译错误,返回值类型不匹配
		return 88; //1.结束方法的执行  2.返回结果(250)给调用方
	}
	
	//有参无返回值
	public static void sayHi(String name){
		System.out.println("大家好,我叫"+name);
		return; //1.结束方法的执行
	}
	
	//无参无返回值
	public static void say(){
		System.out.println("大家好,我叫WKJ");
	}	
}

二、类演示

1 .前言

/*
 *一. 面向过程:数据+方法
 * 	面向过程的缺陷:
 * 		1.缺乏对数据的封装(在main方法中所定义的变量并无直接关系)。
 * 		2.数据和方法(操作数据的)的分离(参数错了容易出错)
 * 二.解决方案:面向对象
 * 类:数据(成员变量)+方法(1.构造方法给成员变量赋值2.类方法:类的行为和功能)
 * 1.面向对象的第一步就是抽象数据类型,所谓抽象数据类型可以理解为:将不同类型的数
 * 	  据的集合组成个整体用来描述一种新的事物。(自造的数据类型)
 * 2.类定义了一种抽象数据类型,而类不但定义了抽象数据类型的组成(成员变量),
 *   同时还定义了对该类型可以实施的操作(方法)。
 * 三.
 * 1.什么是类?什么是对象?
 *   1)现实世界是由很多很多对象组成的 基于对象抽出了类( 类:类型、类别,代表一类个体 泛指)
 * 	 2)对象:真实存在的单个的个体(特指:此创建对象的过程也通常称为实例化具体那一个)
 * 	 3)类中可以包含:
 * 		3.1)所有对象所共有的属性/特征---变量(成员变量)
 * 		3.2)所有对象所共有的行为--------方法
 *   4)类是对象的模板,对象是类的具体的实例
 *  2.定义类的方法:
 *   		类的修饰词(默认public或者不写)  class{成员变量类型+变量名称  类方法   }
 *   注意:一个文件中,可以包含多个类但是public修饰的类只能有一个,并且public修饰的类必须与文件同名
 *   
 */

2 .类演示

public class Student {//学生类
	String name; //成员变量
	int age;
	String address;
	
	void study(){ //方法
		System.out.println(name+"在学习...");
	}
	void sayHi(){
		System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address);
	}
	
}
//学生类的测试类
public class StudentTest {
	public static void main(String[] args) {
		/*		
		 * 使用new关键字创建学生对象
		 * new运算的语法为: new 类名();此创建对象的过程也通常称为实例化。
		 * 类名+引用=new 类名(参数)如果有空的构造也可以:类名+引用=new 类名()
		 * new之后,所有成员变量都有一个默认的初始值:
		 * 成员变量如果是:数值类型(byte,short,char,int,long,float,double)默认:0
		 * 				 boolean类型:false    引用类型NULL 
		 * 为了能够对实例化的对象进行访问控制,需一个特殊的变量,即引用。(zs)
		 * 引用类型变量可以存储该类对象的地址信息,通常称为“指向该类的对象”,
		 * 当一个引用类型变量指向该类的对象,就可以通过这个变量对对象实施访问。
		 * (除8种基本类型之外,用类、接口、数组等声明的变量都称为引用类型变量,简称“引用”) 
		 */
		Student zs = new Student(); 
		/*
		 * 访问成员变量:引用.成员变量
		 */
		zs.name = "zhangsan";
		zs.age = 25;
		zs.address = "河北廊坊";
		/*
		 * 调用类中的方法:1.无返回值:引用.方法名(有参传参)2.:有返回值: 返回值类型 a=引用.方法名(有参传参)
		 * 能.出什么看类型
		 */
		zs.study();
		zs.sayHi();			
		//new之后,所有成员变量都有一个默认的初始值
		Student ww = new Student();
		ww.study();
		ww.sayHi();
		/*引用类型变量存储的是对象的地址信息:引用类型之间画等号:指向同一个对象.
		 *  1)对其中一个引用的修改会影响另外一个  原因:对象只有一份   eg:房子钥匙(一个对象)
		 *  2)基本类型之间画等号:赋值 1)对其中一个变量的修改不会影响另外一个  原因:数据有两份
		 *  eg:身份证复印件(两份身份证) 
		 */
		Student ls=zs;
		/*
		 * null和NullPointerException
		 * null:  1)空,不指向任何对象
		 *    	  2)对null值做任何操作都是不合理的, 报空指针异常(NullPointerException)
		 *    对没有指向对象的引用使用(赋值,调方法啊),
		 */
		Student st=null;
		System.out.println(st.age);//报空指针异常(NullPointerException)	
		
	}
}

3.重载的演示

/*
 * Java语法规定,一个类中不可以有两个方法签名(方法名+参数列表)完全相同的方法。
 * 一个类中不可以有两个方法的方法名和参数列表都完全相同。
 * 如果一个类的两个方法只是方法名相同而参数列表不同,是可以的。(即方法的重载)
 * 方法的重载(overload):
 *  1)在同一个类中,方法名称相同,参数列表不同(参数的类型,个数,顺序有关、但是和返回值类型,参数名称无关)
 *  2)编译器根据签名来绑定调用不同的方法
 *  3)遵循“编译期绑定”看引用类型调用方法(使用哪个类的方法看引用类型,具体调用哪个的看签名) 
 */
//重载的演示
public class OverloadDemo {
	public static void main(String[] args) {
		Aoo o = new Aoo();
		o.say();
		o.say("zhangsan");
		o.say(25);
		o.say("zhangsan", 25);
		o.say(25, "zhangsan");
	}
}

class Aoo{
	void say(){}
	//int say(){return 1;} //编译错误,与返回值类型无关
	void say(String name){}
	//void say(String address){} //编译错误,与参数名称无关
	void say(int age){}
	void say(String name,int age){}
	void say(int age,String name){}	

}

4.构造方法演示

/*1.构造方法:构造函数、构造器、构建器
 * 	1)给成员变量初始化
 * 	2)与类同名,没有返回值类型
 * 	3)在创建对象(new)时被自动调用
 *  4)若自己不写构造,则编译器默认提供一个无参构造, 若自己写了构造,则编译器不再默认提供
 *  5)构造方法可以重载
 * 2.构造方法语法结构
 * 	1)构造方法的名称必须与类名相同。
 * 	2)构造方法没有返回值,但也不能写void。
 *  3)【访问修饰符】类名( ) {构造方法体}访问修饰符只能是public或者不写
 * 3.类方法和构造方法的区别:
 * 	1)类方法:是描述对象的行为,封装对象的功能。构造方法给成员变量初始化的。
 * 	2)语法上:【访问修饰符】返回值类型 方法名称(参数列表) {方法体  } 
 */
public class Student {
	String name; 
	int age;
	/*this:指代当前对象,哪个对象调指的就是哪个对象 在方法中访问成员变量之前默认有个this.
	 *this的用法:
	 *	1)this.成员变量名-----访问成员变量
	 *	2)this.方法名()-------调用方法
	 *	3)this()--------------调用构造方法
	 */
	public Student() {}//默认的构造方法	
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	void study(){
		System.out.println(name+"在学习...");
	}
	void sayHi(){
		System.out.println("大家好,我叫"+name+",今年"+age+"岁了");
	}
	
	/*
	 * 构造方法的重载
	 * 1.声明:Cell ( int  row , int  col ) {}调用:Cell   c1 = new  Cell ( 5 , 6 );
	 * 2.声明:Cell ( )   {  } 调用:Cell  c1 =  new  Cell (  ) ;
	 * this()--------------调用构造方法
	 * 3.声明:Cell (int row) {this(row  , row  );}调用:Cell  c1 =  new  Cell ( 5 ) ; 
	 */
	
}

5.super演示

//super演示
public class SuperDemo {	}
/**
2.继承:
	  1)作用:有利于代码的重用
	  2)通过extends实现继承
	  3)父类:共有的属性和方法
	       子类:特有的属性和方法
	  4)子类继承父类后,子类具有:
	      4.1)父类所共有的
	      4.2)子类所特有的
	  5)一个父类可以有多个子类
	    一个子类只能有一个父类---单一继承
	  6)继承具有传递性
*/
class Aoo{}
class Boo extends Aoo{}
/**
 * 继承中构造方法: * 
  java规定:构造子类之前必须先构造父类
   子类的构造方法中是必须要通过super关键字来调用父类的构造方法的,
   这样才可以保证妥善的初始化继承自父类的成员变量。
    若自己不写则编译默认默认提供super()调父类的无参构造
    若父类没有提供无参的构造方法,则会出现编译错误。
    若自己写了则不再默认提供  super()必须位于子类构造的第一句 .
   2. 用子类构造来初始化子类对象时,父类构造总会在子类构造之前执行。
   3.super:指代当前对象的父类对象
      1)super.成员变量名---访问父类的成员变量
  	  2)super.方法名()-----调用父类的方法
  	  3)super()------------调用父类的构造方法    
 */
class Foo {    
    int value;
    Foo(int value) {
       this.value = value;
    }
}
class Goo extends Foo {   
    int num;
    /*
     * 有两种解决方案,方案一为在父类中添加无参的构造方法.
     * 方案二为在子类构造方法中显示调用父类的有参构造方法(常常使用),
     * 这样可以保证父类的成员变量均被初始化,
     */
    //Goo(int num) {this.num = num;}//父类没有提供无参的构造方法,则会出现编译错误。
    Goo(int value, int num) {
        super(value);
        this.num = num;
    }   
}

package oo.day03;
/*
 * 向上造型:
 * 1)父类型的引用指向子类的对象
 * 2)能点出来什么,看引用的类型
 */
//向上造型的演示
public class UpTypeDemo {
	public static void main(String[] args) {
		Coo o1 = new Coo(); //父只能调父的
		o1.c = 1;
		o1.show();		
		Doo o2 = new Doo(); //子既能调子的也能调父的
		o2.d = 1;
		o2.say();
		o2.c = 2;
		o2.show();		
		Coo o3 = new Doo(); //向上造型
		o3.c = 1;
		o3.show();
		/*
		 * 当用父类型引用指向了子类对象后,java编译器会根据引用的类型(Coo),
		 * 而不是对象的类型(Doo)来检查调用的方法是否匹配。
		 */
		//o3.d = 2; //编译错误,能点出来什么,看引用的类型
	}
}

class Coo{
	int c;
	void show(){}
}
class Doo extends Coo{
	int d;
	void say(){}
}

5.final的演示

/**
final:最终的
1)修饰变量:变量不能被改变
2)修饰方法:方法不能被重写   意义在于:防止子类在定义新方法时造成的“不经意”重写。
3)修饰类:  类不能被继承但是final修饰的类可以继承别的类
*/
//final的演示
public class FinalDemo {public static void main(String[] args) {	}}

final class Poo{}
//修饰类:  类不能被继承但是final修饰的类可以继承别的类
//class Qoo extends Poo{} //编译错误,final的类不能被继承

class Roo{}
final class Soo extends Roo{}

//修饰方法:方法不能被重写
class Noo{
	void show(){}
	final void say(){}
}
class Ooo extends Noo{
	void show(){}
	//void say(){} //编译错误,final的方法不能被重写
}
/*final可以修饰成员变量,也可以修饰局部变量:
 * final修饰成员变量:
 * 1)声明同时初始化或者在构造方法中初始化
 * final修饰局部变量:
 * 1)用之前初始化即可(不用可以不初始化)
 */
//修饰变量:变量不能被改变
class Moo{
	final int a = 5;
	final int b;
	Moo(){
		b = 5;
	}

	void show(){
		final int c;
		//System.out.println(c); //编译错误,使用之前必须初始化
		//a = 55; //编译错误,final的变量不能被改变
	}
}

6.package 包名演示

/**
1.package: package 包名;
  	1)作用:避免类的命名冲突
  	2)包名可以有层次结构(常常有)
  	3)类的完全限定名:包名.类名
 	 4)包名建议:所有字母小写
建议:  域名反写   . 项目名称 . 模块名称 . 类名
          cn.tedu    . tmooc    .  course   .
          com.taobao . tts8     .  student  .
2. import:语法:import 类的全局限定名(即包名+类名);想直接访问  不同包中的类
为了方便起见,在Eclipse中,可以使用“Ctrl+Shift+O”,自动完成import语句。
  1)作用:声明类/引入类
  2)同包之内的类可以直接访问
  3) 不同包中的类,想直接访问:
    	3.1)先import声明类,再直接访问类
    	3.2)类的完全限定名---不推荐
3.3)import  包名+*(意味着声明该包中所有类的全称)
3. 访问控制修饰符:封装访问的权限
 	 1)public:公开的,任何类
 	 2)private:私有的,本类
  	 3)protected:受保护的,本类、子类、同包类
 	 4)默认:什么也不写,本类,同包类
 
  说明:
  1)类的访问修饰符只能是public和默认的(protected和private访问修饰符可以修饰内部类)
  2)类中的成员如上4种修饰符都可以

*/
public class Foo {
	public int a;    //所有
	protected int b; //本,子,同包
	int c;           //本,同包
	private int d;   //本
	
	void show(){
		a = 1;
		b = 2;
		c = 3;
		d = 4;
	}
}

class Goo{ //private
	void show(){
		Foo o = new Foo();
		o.a = 1;
		o.b = 2;
		o.c = 3;
		//o.d = 4;
	}
}

7.重写的演示


/*
 在java语言中,子类可以重写(覆盖)继承自父类的方法,
 即方法名和参数列表与父类的方法相同,但是方法的实现不同。
 子类重写了父类的方法后,该重写方法被调用时
 (无论是通过子类的引用调用还是通过父类的引用调用),运行的都是子类重写后的版本。 
  1.方法的重写(override):重新写、覆盖
    1)发生在父子类中,方法名称相同,参数列表相同,方法体不同。
    2)重写方法被调用时,看对象的类型。
 */
//重写的演示
public class OverrideDemo {
	public static void main(String[] args) {
		/*
		 * 重写遵循"两同两小一大"原则:一般都是完全相同的
		 * 1.两同:
		 *   1)方法名相同
		 *   2)参数列表相同
		 * 2.两小:
		 *   1)子类的返回值类型小于或等于父类的
		 *     1.1)基本类型和void时,必须相同
		 *     1.2)引用类型时,小于或等于
		 *   2)子类抛出的异常小于或等于父类的--异常之后
		 * 3.一大:
		 *   1)子类的访问权限大于或等于父类的--访问控制修饰符后
		 */
	}
}

//父类大,子类小
class Aoo{
	void show(){}
	double say(){return 0.0;}
	Aoo get(){return null;}
	Boo test(){return null;}
}
class Boo extends Aoo{
	void show(){} //void时必须相同
	double say(){return 2.2;} //基本类型时必须相同
	Boo get(){return null;} //正确的,小于
	//Aoo test(){return null;} //错误的,只能小于或等于
}

8.重写与重载的区别

/**
重写与重载的区别----常见面试题
1)重写:
  1.1)发生在父子类中,方法名相同,参数列表相同,方法体不同
  1.2)遵循"运行期绑定",看对象的类型调用方法
2)重载:
  2.1)发生在一个类中,方法名相同,参数列表不同
  2.2)遵循"编译期绑定",看引用的类型绑定方法
  */
//重写与重载的区别
public class OverrideOverloadDemo {
	public static void main(String[] args) {
		//重写:看对象的类型   重载:看引用的类型
		Eoo eoo = new Eoo();
		Coo o = new Doo(); //向上造型
		eoo.test(o);==父类型参数 子类--show 
	}
}
class Coo{
	void show(){
		System.out.println("父类--show");
	}
}
class Doo extends Coo{
	void show(){
		System.out.println("子类--show");
	}
}
class Eoo{
	void test(Coo o){
		System.out.println("父类型参数");
		o.show();
	}
	void test(Doo o){
		System.out.println("子类型参数");
		o.show();
	}
}

9.static的演示

/**
1.static存在的意义就是不需要实例化某个类就可以调用.
    被static修饰的成员变量和成员方法独立于该类的任何对象。
   也就是说,它不依赖类特定的实例,被类的所有实例共享。
   只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。
   因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
 2.静态的存在方法区中,属于类的直到程序停止才消失。静态的可以直接调用静态的,
      而非new来访问格式:类名. 静态的不可以直接调用非静态的(实例变量和方法),非
      静态可以直接调用静态的。  
*/
//static的演示
public class StaticDemo {
	public static void main(String[] args) {
		Joo o1 = new Joo();
		o1.test();//a=1 b=1
		Joo o2 = new Joo();
		//静态变量:属于类,存在方法区中,只有一份
		o2.test();//a=1 b=2
		System.out.println(Joo.b); //2 常常通过类名.来访问
		System.out.println(o1.b); //2 也可以通过对象.来访问		
		//Koo.say();
		//在类被加载时自动执行,因类只被加载一次, 所以静态块也只执行一次
		Loo o3 = new Loo();
		Loo o4 = new Loo();
		Loo o5 = new Loo();		
	}
}

10.静态块演示

class Loo{
	/**
	3)静态块:类实例化或者有静态初始化需求的时候才被加载,JVM加载类时会执行这些静态的代码块。
    	3.1)由static修饰
    	3.2)在类被加载时自动执行,因类只被加载一次, 所以静态块也只执行一次
    3.3)何时用:常常用于初始化静态资源(图片、音频、视频...)
    */
	static{
		System.out.println("静态块");
	}
	Loo(){
		System.out.println("构造方法");
	}
}
class Koo{
	int a;
	static int b;
	void show(){
		a = 1;
		b = 2;
	}
	/**
	2)静态方法:
	    2.1)由static修饰
	    2.2)属于类,存在方法区中,只有一份
	    2.3)常常通过类名.来访问
	    2.4)静态方法没有隐式的this传递,
	        所以静态方法中不能直接访问实例成员
	    2.5)何时用:方法的操作仅与参数有关而与对象无关时使用
		                    调用一个静态方法就是“类名.方法名”,静态方法的使用很简单。一般来说,
		                    静态方法常常为应用程序中的其它类提供一些实用工具所用
	*/
	static void say(){
		/*
		 *静态方法没有隐式this传递,没有this意味着没有对象,
		 *而实例变量a必须通过对象点来访问,所以此处编译错误
		 */
		//a = 1; //编译错误
		b = 2;
	}
}
class Joo{
	/**static:静态的
	  1.静态变量:
	    1.1)由static修饰 
	    1.2)属于类,存在方法区中,只有一份
	    1.3)常常通过类名.来访问
	    1.4)何时用:所有对象数据都一样时使用
	  2.成员变量:分为实例变量和静态变量
	    1)实例变量:属于对象的,存在堆中,必须通过对象.来访问
	    2)静态变量:属于类的,存在方法区中,通过:类名.来访问也可以对象.来访问	 
	  3.static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,
	        或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用–废话),
	        但是不能在其他类中通过类名来直接引用,这一点很重要。     
	 */
	int a;
	static int b;
	Joo(){
		a++;
		b++;
	}
	void test(){
		System.out.println("a="+a);
		System.out.println("b="+b);
	}
}


代码块:
 用{}括起来的代码。
 根据{}的位置可以分为
局部代码块:方法中,局部位置,作用:限定变量作用范围和生命周期。

构造代码块:在类中方法外(成员位置),用{}括起来的代码。

每次调用构造方法执行前,都会执行构造代码块,

作用:把类中不同构造方法中相同的部分提取出来定义到构造代码块中,以后无论调用哪个构造方法都会执行相同操作。可以理解对对象初始化。

静态代码块:在类中方法外(成员位置),用{}括起来,用static修饰。作用:给类进行初始化。
代码块执行顺序:
静态代码块》构造代码块》构造方法

静态代码块:只执行一次

构造代码块:每次创建该类对象,调用构造方法就执行,先于构造方法。
被JVM装载->执行父类的相关代码->如果有静态初始化,先执行静态初始化,且只执行一次,以后即使有该类实例化,也不会再执行->如果有静态代码块,以与静态初始化一样的方式执行->如果有new语句带来的实例化,先为成员变量分配空间,并绑定参数列表,隐式或显式执行super(),即父类的构造方法,->执行非静态代码块-〉执行本类的构造函数-〉执行其他代码
下面通过一个案例进行解析:

package day08;

public class DaiMaKuai {
	static {
		System.out.println("大家好我是静态代码块!");
	}
	
	{
		
		System.out.println("大家好我是构造代码块!");

	}
	
	public DaiMaKuai(){
		System.out.println("大家好我是构造方法!");

	}

}

public class DaiMaKuaiDemo {

	static {
		System.out.println("河南科技大学!");
	}
	public static void main(String[] args) {
		System.out.println("洛阳牡丹甲天下!");
		
		//创建DaiMaKuai类对象
		System.out.println("-------------------------");
		DaiMaKuai dmk = new DaiMaKuai();
		System.out.println("-------------------------");
		DaiMaKuai dmk1 = new DaiMaKuai();

	}

}

输出: 

河南科技大学!
 洛阳牡丹甲天下!
-------------------------
大家好我是静态代码块!
 大家好我是构造代码块!
 大家好我是构造方法!
-------------------------
大家好我是构造代码块!
 大家好我是构造方法!

11.接口演示

/**
1.接口:也是单根性继承的扩展(类只能继承一个)
	  1)是一个标准、规范-----制定方     遵守这个标准,就能干某件事-----API后
	  2)由interface定义:只能包含常量和抽象方法
	  3)接口不能被实例化
	  4)接口是需要被实现的,实现类/子类(遵循标准、规范的类):	  	
	        必须重写接口中的所有抽象方法并且前面必须加public修饰
	  5)一个类可以实现多个接口,用逗号分隔.若既继承又实现时,应先继承后实现
	  6)接口可以继承接口
	    6.1)类和接口之间实现(implements)
	    6.2)接口和接口之间为继承(extends)
        6.3)类和类之间为继承(extends)
2.定义接口语法: interface +接口名{
                                                    常量(public static final)可省略也可以写public
                                                    抽象方法 (public abstract)可省略                         
                                 }
*/
public class InterfaceDemo {
	public static void main(String[] args) {
		//Inter5 o1 = new Inter5(); //编译错误,接口不能被实例化
		Foo    o2 = new Foo();
		Inter6 o3 = new Foo(); //向上造型
		Inter5 o4 = new Foo(); //向上造型		
	}
}
//接口间的继承
interface Inter5{	void a();}
interface Inter6 extends Inter5{	void b();}
class Foo implements Inter6{public void b(){}public void a(){}}
//接口的多实现
interface Inter3{	void a();}
interface Inter4{	void b();}
abstract class Doo{	abstract void c();}
class Eoo extends Doo implements Inter3,Inter4{//先继承后实现
	public void a(){}
	public void b(){}
	void c(){}
}
//接口的实现
interface Inter2{	void a();	void b();}
class Coo implements Inter2{	public void a(){}	public void b(){}}
//演示接口的基础语法
interface Inter1{
	public static final double PI=3.14159;
	public abstract void show();	
	int NUM=2; //默认public static final
	void say(); //默认public abstract	
	//int num2; //编译错误,默认常量,必须声明同时初始化
	//void sayHi(){} //编译错误,默认抽象方法,不能有方法体
}

12.抽象类演示


/**
抽象类:
	  1)由abstract修饰
	  2)包含抽象方法的类必须是抽象类
	    没有抽象方法的类也可以声明为抽象类--我愿意
	  3)抽象类不能被实例化(new对象)但是可以声明抽象类数组Shape[] shapes = new Shape[4];
	  4)抽象类都是需要被继承的,子类:
	    4.1)重写抽象类中的所有抽象方法
	    4.2)也声明为抽象类---一般不这样做
	  5)抽象类的意义:
	    5.1)父类的意义:
	        5.1.1)封装所有子类共有的属性和方法
			5.1.2)为所有子类提供一种公共的类型--向上造型( 抽象类名 引用=new 子类();
	    5.2)可以包含抽象方法,由子类来做不同的实现,但是入口一样(父类都能点出来/方法名)
*/
abstract class Shape{ //抽象类-不完整
	protected double c; //周长
	/**
	抽象方法:也可以将抽象方法理解为不完整的方法。
		  1)由abstract修饰
		  2)只有方法的定义,没有方法的具体实现(连大括号都没有)		  
	*/	  
	public abstract double area(); //抽象方法-不完整
}
class Square extends Shape{
	public Square(double c){
		this.c = c;
	}
	public double area(){ //重写--变不完整为完整
		return 0.0625*c*c;
	}
}
class Circle extends Shape{  //0.0796
	public Circle(double c){
		this.c = c;
	}
	public double area(){
		return 0.0796*c*c;
	}
}



package oo.day05;
//求一组图形中的最大面积
public class ShapeTest {
	public static void main(String[] args) {
		//Shape s1 = new Shape(); //编译错误,抽象类不能被实例化
		Shape[] shapes = new Shape[4]; //创建Shape数组对象
		shapes[0] = new Circle(1); //向上造型
		shapes[1] = new Circle(2); 
		shapes[2] = new Square(1); 
		shapes[3] = new Square(2); 
		maxArea(shapes);
	}
	public static void maxArea(Shape[] shapes){ //求最大面积
		double max = shapes[0].area(); //最大面积
		int maxIndex = 0; //最大面积下标
		for(int i=1;i<shapes.length;i++){
			double area = shapes[i].area();
			if(area>max){
				max = area;
				maxIndex = i;
			}
		}
		System.out.println("最大面积为:"+max+",所在索引为:"+maxIndex);
	}
}
/**
可以总结出如下几点抽象类和接口的区别:
  1.一个类只能继承一个抽象类,但可以实现多个接口。
  2.抽象类中可以包含抽象方法和非抽象方法,而接口中的所有方法均为抽象的。所以的变量都是常量必须声明时初始化。
  3.子类继承抽象类必须实现抽象类中所有抽象方法,否则子类也必须是抽象类。
         而子类实现接口则必须实现接口中的所有抽象方法。
设计规则:
    1)将公共的属性和行为,抽到父类中
    2)所有子类行为都一样,做成普通方法 所有子类行为不一样,做成抽象方法
    3)符合既是也是的规则,使用接口(部分子类共有的行为)
    4)将程序的任务,流程,步骤写到测试类中
*/


13.static final常量的演示

/**
static final:修饰的成员变量称为常量
1)必须声明同时初始化
2)由类名点来访问,并且不能改变
3)建议:常量名所有字母大写
4)常量在编译期被直接替换为具体的值--效率高可以节约不必要的开支
*/
//static final常量的演示
public class StaticFinalDemo {
	public static void main(String[] args) {
		System.out.println(Aoo.PI); //通过类名点来访问
		//Aoo.PI = 3.1415926; //编译错误,常量不能被改变
		/*
		1.方法区中加载Boo.class
		2.num2存储在方法区中
		3.到方法区中获取num2的值并输出
		*/
		System.out.println(Boo.num2);
		
		//在编译期被直接替换为具体的值,效率高
		//相当于System.out.println(100);
		System.out.println(Boo.NUM);
	}
}

class Boo{
	public static final int NUM = 100; //常量
	public static int num2 = 200; //静态变量
}
class Aoo{
	public static final double PI=3.14159;
	//public static final int NUM; //编译错误,必须声明同时初始化
}


14.成员内部类演示

/**
成员内部类:
	  1)类中套类,里面的称为内部类类称之为Inner,外面的称为外部类称之为Outer
	  2)内部类通常只服务于外部类,对外不具备可见性(不能实例化在其它类中)
	  	一般情况下,Inner对象会在Outer对象中创建(构造方法或其他方法);
	  3)内部类对象通常是在外部类中创建
	  4)内部类中可以直接访问外部类中的成员(包括私有的)
	        内部类中有一个隐式的引用指代创建它的外部类的对象
	        外部类名.this.----eg: Mama.this.
*/  	      
//成员内部类演示
public class InnerClassDemo {
	public static void main(String[] args) {
		Mama m = new Mama();
		//Baby b = new Baby(); //编译错误,内部类对外不具备可见性
	}
}

class Mama{
	private String name;
	Baby createBaby(){
		Baby b = new Baby();
		return b;
	}
	class Baby{
		void showMamaName(){
			System.out.println(name);
			System.out.println(Mama.this.name);
			//System.out.println(this.name); //this为当前对象,即Baby类对象,而Baby类没有name属性
		}
	}
}

15.多态的演示

/**
1.多态:(都造了型向上造型)
	  1)多态的意义:
	    1.1)同一类型的引用指向不同对象时,有不同的实现 ----行为的多态: cut()
	    1.2)同一个对象被造型为不同类型时,有不同的功能  ----对象的多态: 我
	  2)向上造型:
	    2.1)父类型的引用指向子类的对象
	    2.2)能向上造型为的类型: 父类、所实现的接口
	    2.3)能点出来什么,看引用的类型  重写方法被调用时,看对象的类型
	  3)强制类型转换,成功的条件:
	    3.1)引用所指向的对象,就是该类型
	    3.2)引用所指向的对象,实现了该接口
	  4)强转若不符合如上两个条件,则发生类型转换异常,(Class cast Exception)
	    建议:强转之前先通过instanceof来判断,而后再强转
	      instanceof判断引用的对象是否是某类型,返回boolean型结果
	             强转成功的条件就是它为true的条件



		cut()行为就是多态的
			人 p1 = new 理发师();
			人 p2 = new 外科医生();
			人 p3 = new 演员();

			p1.cut(); //剪发
			p2.cut(); //开刀
			p3.cut(); //停止表演



			abstract class 人{
			  abstract cut();
			}
			class 理发师{
			  cut(){ 剪发 }
			}
			class 外科医生{
			  cut(){ 开刀 }
			}
			class 演员{
			  cut(){ 停止表演 }
			}

*/	              
//多态的演示
public class MultiTypeDemo {
	public static void main(String[] args) {
		Aoo o1 = new Boo();     //向上造型
		Boo o2 = (Boo)o1;       //o1指向的对象就是Boo类型
		Inter1 o3 = (Inter1)o1; //o1指向的对象实现了Inter1接口
		//Coo o4 = (Coo)o1; //类型转换异常
		if(o1 instanceof Coo){ //false
			Coo o5 = (Coo)o1;
		}
	}
}

interface Inter1{}
class Aoo{}
class Boo extends Aoo implements Inter1{}
class Coo extends Aoo{}

水作为不同形态时,所能干的事也是不一样的
我这个对象是多态的
我 me = new 我();
讲师       o1 = me; //向上造型
孩子他妈   o2 = me;
老公的老婆 o3 = me;
o1.讲课();
o2.揍他();
o3.咬他();
o3.收工资();
interface 讲师{  讲课();}
interface 孩子他妈{  揍他();}
interface 老公的老婆{  咬他();  收工资();}
class 我 implements 讲师,孩子他妈,老公的老婆{  讲课(){}  揍他(){}  咬他(){}  收工资(){}}

run()行为也是多态的
动物 a1 = new 老虎();
动物 a2 = new 鱼();
动物 a3 = new 鸟();
a1.run();
a2.run();
a3.run();

abstract class 动物{  abstract run();}
class 老虎 extends 动物{  run(){ 在地上跑 }}
class 鱼 extends 动物{  run(){ 在水里游 }}
class 鸟 extends 动物{  run(){ 在天上飞 }}
cut()行为就是多态的
人 p1 = new 理发师();
人 p2 = new 外科医生();
人 p3 = new 演员();

p1.cut(); //剪发
p2.cut(); //开刀
p3.cut(); //停止表演

16.匿名内部类演示

/**
 匿名内部类:
1.如果在一段程序中需要创建一个类的对象(通常这个类需要实现某个接口或者继承某个类),
    而且对象创建后,这个类的价值也就不存在了,这个类可以不必命名,称之为匿名内部类。
  1)想创建一个类的对象,并且对象只创建一次, 该类不必命名,称之为匿名内部类
  2)匿名内部类中访问外面的变量,该变量必须是final的
  3)内部类有独立的.class
2.匿名内部类的结构:Inter2 o2 = new Inter2(){			};	
		    2.1)用匿名类所实现的接口或所继承的父类类型声明的引用;
		    2.2)new 后面的为匿名类所要实现的接口或继承的父类;
		    2.3)小括号()中为构造方法参数;
		    2.4)大括号中为匿名中定义的成员变量或方法。
		    (如果父类中有抽象方法子类必须重写抽象方法)
 */ 
//匿名内部类演示
public class NstClassDemo {
	public static void main(String[] args) {
		//Inter2 o1 = new Inter2(); //编译错误,接口不能被实例化	
		/**
		1.创建了Inter2的一个子类,没有名字
		2.为该子类创建了一个对象,名为o1
		3小括号()中为构造方法参数
		4.大括号中的为子类的类体(为匿名中定义的成员变量或方法。)		
		*/
		Inter2 o1 = new Inter2(){		};		
		//1.创建了Inter2的一个子类,没有名字
		//2.为该子类创建了一个对象,名为o2
		//3.大括号中的为子类的类体
		Inter2 o2 = new Inter2(){	
			
		};	
		final int num=250;
		/*o3为Inter3子类的对象
		 * run()为Inter3子类的方法
		 */
		Inter3 o3 = new Inter3(){
			public void run(){
				System.out.println("abc");
				System.out.println(num); //num必须是final的
			}
		};
		/*o3为Inter3子类的对象,run()为Inter3子类的方法
		 * o3.run()为调用子类的方法
		 */
		o3.run();		
	}
}
interface Inter3{	public void run();}
interface Inter2{}
/**
 4.面向对象三大特征:封装、继承、多态
  1)封装:
    1.1)类:封装对象的属性和行为
    1.2)方法:封装具体的功能的实现
    1.3)访问控制修饰符:封装访问的权限
  2)继承:
    2.1)作用:有利于代码的复用
    2.2)父类/基类:共有的
        子类/派生类:特有的
    2.3)子继承父后,具有:父的+子的
  3)多态:
    3.1)意义:行为的多态、对象的多态
    3.2)向上造型、强制类型转换、instanceof
    3.3)表现形式:
          重写、重载
 */         

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值