static静态关键字

当在定义类的时候,类中都会有相应的属性和方法。而属性和方法都是通过创建本类对象调用的。当在调用对象的某个方法时,这个方法没有访问到对象的特有数据时,创建这个对象有些多余。可是不创建对象,方法又调用不了,这时我们可以通过static关键字来实现不创建对象,也可以调用方法。static是静态修饰符,一般用来修饰类中的成员。

案例代码-静态的特点

package com.Object;

/*
 * static:是一个关键字,用于修饰成员变量和成员方法
 * static的特点:
 * 			被所有的对象所共享
 * 			可以使用类名调用
 * 			静态的加载优先于对象
 * 			随着类的加载而加载
 * 
 */
public class Demo {
	public static void main(String[] args) {
		Person.graduateFrom = "123学院";
		Person p = new Person();
		p.name = "小苍同学";
		p.age = 18;
		p.speak();

		Person p2 = new Person();
		p2.name = "小波同学";
		p2.age = 20;
		p2.speak();
	}

}

class Person {
	String name;
	int age;
	static String graduateFrom;// 毕业院校

	public void speak() {
		System.out.println(name + "---" + graduateFrom);
	}
}

案例代码-注意事项

package com.Object;
/*
 * static的注意事项:
 * 			静态方法:
 * 				可以调用静态的成员变量
 * 				可以调用静态的成员方法
 * 				不可以调用非静态成员变量
 * 				不可以调用非静态成员方法
 * 				静态方法只能调用静态的成员
 * 			非静态方法:
 * 				可以调用静态的成员变量
 * 				可以调用静态的成员方法
 * 				可以调用非静态的成员变量
 * 				可以调用非静态的成员方法
 * 		
 * 	静态的方法中是否有this这个对象?没有的
 * 				
 * 
 */

public class Demo2 {
	public static void main(String[] args) {
		Student.graduateFrom = "123学院";
		Student.study();
	}

}

class Student {
	String name;
	int age;
	static String graduateFrom;//毕业院校
	
	public static void study() {
		System.out.println(graduateFrom);
		sleep();
		
		System.out.println(name);
		
		eat();
		
	}
	
	public static void sleep() {
		System.out.println("sleep");
		
	}
	
	public void eat() {
		System.out.println("eat");
		
		System.out.println(graduateFrom);
		sleep();
		
		
	}
	
}

静态应用

案例代码-Math类

package com.Object;
public class Demo3 {
	public static void main(String[] args) {
		//Math:包含了一些基本的数学运算方法
		//static double PI  
		//System.out.println(Math.PI);
		
		//static double abs(double a)  :返回绝对值
		//System.out.println(Math.abs(15));
		System.out.println(Math.abs(-10));
		
		//static double ceil(double a) 天花板   向上取整
		//System.out.println(Math.ceil(1.2));
		System.out.println(Math.ceil(1.6));
		//static double floor(double a)  地板  向下取整
		System.out.println(Math.floor(1.2));
		//System.out.println(Math.floor(1.6));
		
		//static long round(double a)  :四舍五入
		//System.out.println(Math.round(1.2));
		//System.out.println(Math.round(1.6));
		
		//static double max(double a, double b) 
		//System.out.println(Math.max(3, 4));
		
		//static double pow(double a, double b) :返回第一个参数的第二个参数次幂
		System.out.println(Math.pow(3, 2));
		
		//static double random() :返回一个随机数,大于零且小于一
		System.out.println(Math.random());
		
		
		 
	}

}

案例代码-自定义类

package com.Object;

public class MyArrays {
	private MyArrays() {
	}

	// 返回数组中最大的元素
	public static int getMax(int[] arr) {
		int max = 0;// 参照物
		// 遍历数组
		for (int x = 0; x < arr.length; x++) {
			if (arr[x] > max) {
				max = arr[x];// 替换参照物
			}
		}

		return max;
	}

	// 返回数组中指定参数的索引
	public static int getIndex(int[] arr, int a) {
		// 遍历数组
		for (int x = 0; x < arr.length; x++) {
			if (arr[x] == a) {
				return x;
			}
		}

		return -1;// 如果查不到制定的参数,则返回-1
	}
}
package com.Object;

public class Demo4 {
	public static void main(String[] args) {
		int[] arr = { 3, 5, 8, 10, 1 };
		int max = MyArrays.getMax(arr);
		System.out.println(max);

		int index = MyArrays.getIndex(arr, 8);
		System.out.println(index);

	}

}

类变量与实例变量辨析

A:类变量:其实就是静态变量
定义位置:定义在类中方法外
所在内存区域:方法区
生命周期:随着类的加载而加载
特点:无论创建多少对象,类变量仅在方法区中,并且只有一份

B:实例变量:其实就是非静态变量
定义位置:定义在类中方法外
所在内存区域:堆
生命周期:随着对象的创建而加载
特点:每创建一个对象,堆中的对象中就有一份实例变量

代码块

案例代码-局部代码块

package com.Block;

public class Demo {
public static void main(String[] args) {
		//局部代码块:存在于方法中,控制变量的生命周期(作用域)
		 {
			for(int x = 0;x < 10;x++) {
				System.out.println("我爱Java");
			}
			int num = 10;
		}
		//System.out.println(num);//无法访问num,超出num的作用域范围
 
	}

}

案例代码-构造代码块

package com.Block;

/*构造代码块是定义在类中成员位置的代码块*/
class Teacher {
	String name;
	int age;
	
	{
		for(int x = 0;x < 10;x++) {
			System.out.println("我爱Java");
		}
		System.out.println("我爱Java");
	} 
	
	 
	
	public Teacher() {
		System.out.println("我是无参空构造");
	}
	
	public Teacher(String name,int age) {
		System.out.println("我是有参构造");
		
		this.name = name;
		this.age = age;
	}
}

案例代码-静态代码块

package com.Block;

class test {
	String name;
	int age;
 
	//静态代码块:随着类的加载而加载,只加载一次,加载类时需要做的一些初始化,比如加载驱动
	static {
		System.out.println("我爱Java");
	}
	
	public test() {
		System.out.println("我是无参空构造");
	}
	
	public test(String name,int age) {
		System.out.println("我是有参构造");
		
		this.name = name;
		this.age = age;
	}
	
	
}

代码块特点

局部代码块:

以”{}”划定的代码区域,此时只需要关注作用域的不同即可

方法和类都是以代码块的方式划定边界的

构造代码块

优先于构造方法执行,构造代码块用于执行所有对象均需要的初始化动作

每创建一个对象均会执行一次构造代码块。

静态代码块

它优先于主方法执行、优先于构造代码块执行,当以任意形式第一次使用到该类时执行。

该类不管创建多少对象,静态代码块只执行一次。

可用于给静态变量赋值,用来给类进行初始化。

继承

继承的概述

现实生活中,继承一般指的是子女继承父辈的财产。在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系。

案例代码-格式

package com.Extends;
/*
 * 继承:多个类有共同的成员变量和成员方法,抽取到另外一个类中(父类)
 * 再让多个类去继承这个父类,我们的多个类就可以获取到父类中的成员了。
 * extends
 * 
 */

public class Demo {
	public static void main(String[] args) {
		DotA1 d = new DotA1();
		d.start();

		LOL1 l = new LOL1();
		l.start();
	}

}

class Game1 {
	String name;
	double version;// 版本号
	String agent;// 代理商

	public void start() {
		System.out.println("游戏启动了");
	}

	public void stop() {
		System.out.println("游戏关闭了");
	}
}

class DotA1 extends Game1 {
	/*
	 * String name; double version;//版本号 String agent;//代理商
	 * 
	 * public void start() { System.out.println("游戏启动了"); }
	 * 
	 * public void stop() { System.out.println("游戏关闭了"); }
	 */
}

class LOL1 extends Game1 {
	/*
	 * String name; double version;//版本号 String agent;//代理商
	 * 
	 * public void start() { System.out.println("游戏启动了"); }
	 * 
	 * public void stop() { System.out.println("游戏关闭了"); }
	 */

}

继承的特点

1、在Java中,类只支持单继承,不允许多继承,也就是说一个类只能有一个直接父类,例如下面这种情况是不合法的。

class A{}

     class B{}

     class C extends A,B{}  // C类不可以同时继承A类和B类

2、多个类可以继承一个父类,例如下面这种情况是允许的。

     class A{}

     class B extends A{}

     class C extends A{}   // 类B和类C都可以继承类A

3、在Java中,多层继承是可以的,即一个类的父类可以再去继承另外的父类,例如C类继承自B类,而B类又可以去继承A类,这时,C类也可称作A类的子类。下面这种情况是允许的。

     class A{}

     class B extends A{}   // 类B继承类A,类B是类A的子类

     class C extends B{}   // 类C继承类B,类C是类B的子类,同时也是类A的子类

4、在Java中,子类和父类是一种相对概念,也就是说一个类是某个类父类的同时,也可以是另一个类的子类。例如上面的这种情况中,B类是A类的子类,同时又是C类的父类

案例代码-继承的特点

package com.Extends;
/*
 * Java中继承的特点:
 * 			Java语言只支持单一继承,只能继承一个父类(一个儿子只能有一个亲爹)
 * 			Java语言支持多层继承(一个儿子可以有一个亲爹,还可以有一个亲爷爷)
 * 
 */
public class Demo2 {
	public static void main(String[] args) {
		LOL l = new LOL();
		l.update();
		l.start();
	}

}

class Game {
	public void start() {
		System.out.println("游戏启动了");
	}
}

class PCGame extends Game {
	public void update() {
		System.out.println("PCGame更新了");
	}
}

class MobileGame extends PCGame {
	public void update() {
		System.out.println("MobileGame更新了");
	}
}

class LOL extends MobileGame {
	
}

案例代码-继承成员变量的特点

package com.Extends;
/*
 * 继承中成员变量的特点
 * 		子类只能获取父类非私有成员
 * 		子父类中成员变量的名字不一样直接获取父类的成员变量
 * 		子父类中成员变量名字是一样的获取的是子类的成员变量
 * 
 * 就近原则:谁离我近我就用谁
 * 		如果有局部变量就使用局部变量
 * 		如果没有局部变量,有子类的成员变量就使用子类的成员变量
 * 		如果没有局部变量和子类的成员变量,有父类的成员变量就使用父类的成员变量
 * 		啥都没有,出错了!!!
 * 
 * super:可以获取父类的成员变量和成员方法,用法和this是相似的
 */

public class Demo3 {
	public static void main(String[] args) {
		Kid3 k = new Kid3();
		k.show();
	}

}

class Dad3 {
	String name = "建霖";
}

class Kid3 extends Dad3 {
	String name = "四葱";

	public void show() {
		String name = "五葱";

		System.out.println(super.name);
		System.out.println(this.name);
		System.out.println(name);
	}
}

案例代码-继承中成员方法的特点A

package com.Extends;
/*
 * 继承中成员方法的特点A
 * 		子类中没有这个方法,调用父类的
 */

public class Demo4 {
	public static void main(String[] args) {
		Kid4 k = new Kid4();
		k.eat();
	}

}
class Dad4 {
	public void eat() {
		System.out.println("小酌两口");
		System.out.println("去睡觉了");
	}
}

class Kid4 extends Dad4 {
   
}

案例代码-继承中成员方法的特点B

package com.Extends;
/*
 * 继承中成员方法的特点B
 * 		子类中重写了这个方法,调用子类的
 * 
方法的重写:在子父类当中,子类的方法和父类的完全一样,子类重写了父类的方法(覆盖),当子类重写了父类的方法之后,使用子类对象调用的就是子类的方法
方法的重载:在一个类中,有多个重名的方法,但是其参数不一样(参数的个数,参数的类型,参数的顺序),和返回值无关
 */

public class Demo5 {
	public static void main(String[] args) {
		Kid6 k = new Kid6();
		k.eat();
	}

}

class Dad6 {
	public void eat() {
		System.out.println("小酌两口");
		System.out.println("去睡觉了");
	}
}

class Kid6 extends Dad6 {
	public void eat() {
		System.out.println("好好吃饭");
	}
}


方法重写的应用场景&注意事项

案例代码-方法重写

package com.Extends;
/*
 * 	方法重写的应用场景:当父类的方法不能完全满足子类使用,这个时候子类重写父类的方法,
 * 				    并可以在方法中使用关键字super调用父类的方法,这样做即可以保有父类的功能,也可以拥有子类特有的功能
 *  方法重写的注意事项:
 *  			  不能重写父类私有的方法
 *  			 权限必须大于等于父类方法的权限
 */

public class Demo6 {
	public static void main(String[] args) {
		NewPhone np = new NewPhone();
		np.call();
	}

}

class Phone {
	void call() {
		System.out.println("打电话");
	}
}

class NewPhone extends Phone {

	@Override
	public void call() {
		System.out.println("录音");
		// System.out.println("打电话");

		// super.call();
	}
}

继承中构造方法的执行顺序

A:super(实参列表);语句  在子类的构造方法中使用,用来调用父类中的构造方法(具体哪一个由传递的参数决定),并且只能在构造方法第一行使用

   B:this(实参列表); 语句  在类的构造方法中使用,用来调用本类中的其它构造方法(具体哪一个由传递的参数决定),并且只能在构造方法的第一行使用

案例代码-继承中构造方法

package com.Extends;
/*
 * 继承中构造方法的执行顺序
 * 			在子父类中,创建子类对象,调用子类的构造方法,
 * 			在子类的构造方法的第一行代码如果没有调用父类的构造或者没有调用子类的其他构造,则默认调用父类无参构造
 * 为什么要调用父类构造?
 * 			因为需要给父类的成员变量初始化
 * 肯定会先把父类的构造执行完毕,在去执行子类构造中的其他代码
 * 
 * 我是父类无参构造 --- 我是子类有参构造 --- 我是子类无参构造
 */

public class Demo7 {
	public static void main(String[] args) {
		// Die d = new Die();
		Zi6 z = new Zi6();
	}

}

class Die6 {
	public Die6() {
		System.out.println("我是父类无参构造");
	}

	public Die6(int num) {
		System.out.println("我是父类有参构造");
	}
}

class Zi6 extends Die6 {
	public Zi6() {
		// super(1);
		// super();

		this(1);// 不会再调用父类的无参构造了

		System.out.println("我是子类无参构造");
	}

	public Zi6(int num) {
		// 会默认调用父类无参构造
		System.out.println("我是子类有参构造");
	}
}

案例代码-this与super区别

package com.Extends;
/*
 * this和super的区别
		this:当前对象的引用
			调用子类的成员变量
			调用子类的成员方法
			在子类的构造方法第一行调用子类其他构造方法
		super:子类对象的父类引用
			调用父类的成员变量
			调用父类的成员方法
			在子类的构造方法第一行调用父类的构造方法
 */
public class Demo8 {
	public static void main(String[] args) {
		Zi z = new Zi();
		z.function();
	}

}
class Die {
	int num = 10;
	
	public Die() {
		System.out.println("我是父类无参构造");
	}
	
	public Die(int num) {
		System.out.println("我是父类有参构造");
	}
	
	public void method() {
		System.out.println("我是父类的方法");
	}
}


class Zi extends Die {
	//int num = 30;
	
	public Zi() {
		//this(1);//第一行不调用子类其他构造或者是父类构造,默认调用父类无参构造
		super();
		System.out.println("我是子类无参构造");
	}
	
	public Zi(int num) {
		System.out.println("我是子类有参构造");
	}
	
	public void method() {
		System.out.println("我是子类的方法");
	}
	
	public void function() {
		//this.num = 50;
		//System.out.println(num);
		//this.method();
		
		//super.num = 40;
		//super.method();
		
		System.out.println(this.num);
	}
}

继承优缺点

A:优点

提高了代码的复用性

提高了代码的可维护性

B:缺点:

类的耦合性增强了

开发的原则:高内聚低耦合

内聚:就是自己完成某件事情的能力

耦合:类与类的关系

抽象类

抽象类概述

当编写一个类时,往往会为该类定义一些方法,这些方法是用来描述该类的功能具体实现方式,那么这些方法都有具体的方法体。但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。比如一个图形类应该有一个求周长的方法,但是不同的图形求周长的算法不一样。那该怎么办呢? 分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是方法功能声明相同,但方法功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。

案例代码-abstract

package com.Abstract;
/*
 * abstract:关键字,用于修饰方法和类
 * 抽象方法:不同类的方法是相似,但是具体内容又不太一样,所以我们只能抽取他的声明,没有具体的方法体,没有具体方法体的方法就是抽象方法
 * 抽象类:有抽象方法的类必须是抽象类
 * 
 * 注意:一个类继承了抽象类需要重写他所有的抽象方法,否则这个类就得是抽象类
 */

public class Demo {

}

abstract class Animal1 {
	public abstract void eat();

	// 非抽象方法子类可以不重写
	public void run() {

	}
}

class Cat1 extends Animal1 {

	@Override
	public void eat() {
		System.out.println("猫吃鱼");

	}

	/*
	 * public void eat() { System.out.println("猫吃鱼"); }
	 */
}

abstract class Dog1 extends Animal1 {
	/*
	 * public void eat() { System.out.println("狗吃屎"); }
	 */
}

案例代码-抽象类的特点

package com.Abstract;
/*
 * 抽象类的特点:
 * 		抽象方法只能在抽象类里面
 * 		抽象类和抽象方法必须被abstract修饰
 * 		抽象类不能创建对象(不能实例化)
 * 		抽象类中可以有非抽象的方法
 * 		抽象类和类的关系也是继承
 * 		一个类继承了抽象类要么重写所有的抽象方法,要么他自己是抽象类
 */

public class Demo2 {
	public static void main(String[] args) {
		// Animal a = new Animal();
		Cat2 cat2=new Cat2();
		cat2.eat();
	}

}

abstract class Animal2 {
	public abstract void eat();

	public void run() {

	}
}

class Cat2 extends Animal2 {

	@Override
	public void eat() {
		// TODO Auto-generated method stub

	}

}

案例代码-抽象类成员的特点

	package com.Abstract;
	/*
	 * 抽象类的成员特点:
	 * 		成员变量
	 * 			可以有成员变量
	 * 			可以有常量
	 * 		成员方法
	 * 			可以有抽象方法
	 * 			可以有非抽象方法
	 * 		构造方法
	 * 			可以有构造方法的,需要对抽象类的成员变量进行初始化
	 * 
	 * final:修饰类、成员变量、成员方法
	 */
	
	public class Demo3 {
		public static void main(String[] args) {
			Dog d = new Dog();
			d.barking();
		}
	
	}
	
	abstract class Animal {
		String name = "哮天犬";
		final int num = 10;
	
		public Animal() {
			System.out.println("我是抽象类的构造方法");
		}
	
		public abstract void eat();
	
		public void run() {
		}
	}
	
	class Dog extends Animal {
		public void barking() {
			System.out.println(name);
			System.out.println(num);
		}
	
		@Override
		public void eat() {
			// TODO Auto-generated method stub
	
		}
	}

接口

接口的概述

接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计。

接口的格式

与定义类的class不同,接口定义时需要使用interface关键字。

定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以让我们将接口看做是一种只包含了功能声明的特殊类。

public interface 接口名 {
抽象方法1;
抽象方法2;
抽象方法3;
}

接口的使用

接口中的方法全是抽象方法,直接new接口来调用方法没有意义,Java也不允许这样干

类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements

其他类(实现类)实现接口后,就相当于声明:”我应该具备这个接口中的功能”。实现类仍然需要重写方法以实现具体的功能。

class 类 implements 接口 {
	重写接口中方法
} 

在类实现接口后,该类就会将接口中的抽象方法继承过来,此时该类需要重写该抽象方法,完成具体的逻辑。

案例代码-接口

package com.Interface;

/*
 * Java语言的继承是单一继承,一个子类只能有一个父类(一个儿子只能有一个亲爹)
 * Java语言给我们提供了一种机制,用于处理继承单一的局限性的,接口
 * 
 * 接口:接口是一个比抽象类还抽象的类,接口里所有的方法全是抽象方法,接口和类的关系是实现,implements
 * interface
 * 
 * 格式:
 * 		interface 接口名 {
 * 
 * 		}
 * 
 */
public class Demo1 {
	public static void main(String[] args) {
		BillGates gates = new BillGates();
		gates.code();
	}

}

class Boss {
	public void manage() {
		System.out.println("管理公司");
	}
}

class Programmer {
	public void code() {
		System.out.println("敲代码");
	}
}

//比尔盖茨
class BillGates extends Programmer {

}

案例代码-接口中成员特点

package com.Interface;
/*
 * 接口的成员特点:
 * 		只能有抽象方法
 * 		只能有常量
 * 		默认使用public&abstract修饰方法
 * 		只能使用public&abstract修饰方法
 * 		默认使用public static final来修饰成员变量
 * 
 * 建议:建议大家手动的给上默认修饰符
 * 
 * 注意:
 * 		接口不能创建对象(不能实例化)
 * 		类与接口的关系是实现关系,一个类实现一个接口必须实现它所有的方法

 */

public class Demo2 {
	public static void main(String[] args) {
		// Animal a = new Animal();
		 //Animal.num;
	}

}

interface Animal {
	public static final int num = 10;

	public abstract void eat();
}

class Cat implements Animal {

	public void eat() {

	}

}

案例代码-接口和类的关系

package com.Interface;
/*
 * 
 * 类与类:继承关系,单一继承,多层继承
 * 类与接口:实现关系,多实现
 * 接口与接口的关系:继承关系,多继承
 */

public class Demo3 {
	public static void main(String[] args) {

	}

}

interface InterA extends InterB {
	public abstract void method();
}

interface InterB {
	public abstract void function();
}

interface InterC extends InterA {

}

class Demo implements InterC {

	@Override
	public void method() {
		// TODO Auto-generated method stub

	}

	@Override
	public void function() {
		// TODO Auto-generated method stub

	}
}

匿名对象&final

案例代码-匿名对象

package com.AnonymousObejct;
/*
 * 匿名对象:没有名字的对象
 * 匿名对象的应用场景:
 * 		当方法只调用一次的时候可以使用匿名对象
 * 		可以当作参数进行传递,但是无法在传参之前做其他的事情
 * 	
 * 注意:匿名对象可以调用成员变量并赋值,但是赋值并没有意义
 * 			
 */

public class Demo {
	public static void main(String[] args) {
		//Student s = new Student();
		//s.study();
		//s.study();
		//s.study();
		
		//new Student();//匿名对象,没有变量引用的对象
		//new Student().study();
		//new Student().study();
		//new Student().study();
		
		//new Student().age = 18;
		//System.out.println(new Student().age);
		
		
		//Student s = new Student();
		//s.age = 18;
		//s.name = "张三";
		//method(s);
		
		method(new Student());
		
	}
	
	public static void method(Student s) {
		
	}

		
}


class Student {
	String name;
	int age;
	
	public void study() {
		System.out.println("好好学习");
	}
}

案例代码-final关键字

package com.AnonymousObejct;
/*
 * final: 修饰符,可以用于修饰类、成员方法和成员变量
 * final所修饰的类:不能被继承,不能有子类
 * final所修饰的方法:不能被重写
 * final所修饰的变量:是不可以修改的,是常量
 * 
 * 常量:
 * 		字面值常量:1,2,3
 * 		自定义常量:被final所修饰的成员变量,一旦初始化则不可改变
 * 
 * 注意:自定义常量必须初始化,可以选择显示初始化或者构造初始化
 * 
 *  
 */

public class Demo2 {
	public static void main(String[] args) {
		// Animal a = new Animal();
		// a.eat();

		Dog d = new Dog();
		// d.eat();

		// d.num = 20;
		System.out.println(d.NUM);
	}
}

/* final */ class Animal {
	public final void eat() {
		System.out.println("吃东西");
	}
}

class Dog extends Animal {
	/* public void eat() {} */

	final int NUM;

	public Dog() {
		NUM = 10;
	}
}

多态

多态概述

多态是继封装、继承之后,面向对象的第三大特性。

现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。      

Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。

多态的定义与使用格式

多态的定义格式:就是父类的引用变量指向子类对象

父类类型  变量名 = new 子类类型();
变量名.方法名();

A:普通类多态定义的格式

父类 变量名 = new 子类();
如:	class Fu {}
	class Zi extends Fu {}
	//类的多态使用
Fu f = new Zi();

B:抽象类多态定义的格式

抽象类 变量名 = new 抽象类子类();
如:	abstract class Fu {
         public abstract void method();
	     }
class Zi extends Fu {
public void method(){
		      System.out.println(“重写父类抽象方法”);
}
}
//类的多态使用
Fu fu= new Zi();

C:接口多态定义的格式

接口 变量名 = new 接口实现类();
如: interface Fu {
		     public abstract void method();
}
class Zi implements Fu {
		     public void method(){
              System.out.println(“重写接口抽象方法”);
}
}
//接口的多态使用
Fu fu = new Zi();

案例代码-多态

package com.Polymorphic;
/*
 * 多态的前提:
 * 	子父类的继承关系
 * 	方法的重写
 * 	父类引用指向子类对象
 * 
 * 动态绑定:运行期间调用的方法,是根据其具体的类型
 */

public class Demo1 {
	public static void main(String[] args) {
		/*
		 * Cat c = new Cat(); c.eat();
		 */

		// 父类引用 Animal a
		// 指向 =
		// 子类对象 new Cat()

		Animal a = new Cat();
		a.eat();

	}
}

class Animal {
	public void eat() {
		System.out.println("吃东西");
	}
}

class Cat extends Animal {
	public void eat() {
		System.out.println("猫吃鱼");
	}
}

案例代码-多态成员特点

package com.Polymorphic;
/*
 *	
 * 	多态的成员特点:
 * 		成员变量  编译时看的是左边,运行时看的左边
 * 		成员方法  编译时看的是左边,运行时看右边
 * 		静态方法  编译时看的是左边,运行时看的也是左边
 * 
 * 
 * 编译时看的都是左边,运行时成员方法看的是右边,其他(成员变量和静态的方法)看的都是左边
 * 
 */

public class Demo2 {
	public static void main(String[] args) {
		Dad d = new Kid();
		// System.out.println(d.num);

		// d.method();
		d.function();// 使用变量去调用静态方法,其实相当于用变量类型的类名去调用
	}
}

class Dad {
	int num = 20;

	public void method() {
		System.out.println("我是父类方法");
	}

	public static void function() {
		System.out.println("我是父类静态方法");
	}
}

class Kid extends Dad {
	int num = 10;

	public void method() {
		System.out.println("我是子类方法");
	}

	public static void function() {
		System.out.println("我是子类静态方法");
	}
}

多态中向上转型与向下转型

多态的转型分为向上转型与向下转型两种:

A:向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。

父类类型  变量名 = new 子类类型();
如:Person p = new Student();

B:向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的

子类类型 变量名 = (子类类型) 父类类型的变量;
如:Student stu = (Student) p;  //变量p 实际上指向Student对象

案例代码-转型

package com.Polymorphic;
/*
 *	
 * 	多态中的向上转型和向下转型:
 * 
 *  引用类型之间的转换
 *  	向上转型
 *  		由小到大(子类型转换成父类型)
 *  	向下转型
 *  		由大到小
 *  基本数据类型的转换
 *  	自动类型转换
 *  		由小到大
 *  		byte short char --- int --- long --- float --- double
 *  	强制类型转换
 *  		由大到小
 *  		
 * 	
 * 
 */

public class Demo3 {
	public static void main(String[] args) {
		Animal2 a = new Dog();// 向上转型
		// a.eat();

		Dog d = (Dog) a;// 向下转型
		d.swim();

	}
}

class Animal2 {
	public void eat() {
		System.out.println("吃东西");
	}
}

class Dog extends Animal2 {
	public void eat() {
		System.out.println("啃骨头");
	}

	public void swim() {
		System.out.println("狗刨");
	}
}

案例代码-优缺点

package com.Polymorphic;
/*
 *	
 * 	多态的优缺点
 * 		优点:可以提高可维护性(多态前提所保证的),提高代码的可扩展性
		缺点:无法直接访问子类特有的成员
 */

public class Demo4 {
	public static void main(String[] args) {
		MiFactory factory = new MiFactory();
		factory.createPhone(new MiNote());

		factory.createPhone(new RedMi());
	}

}

class MiFactory {
	/*
	 * public void createPhone(MiNote mi) { mi.call(); }
	 * 
	 * public void createPhone(RedMi mi) { mi.call(); }
	 */

	public void createPhone(Phone p) {
		p.call();
	}

}

interface Phone {
	public void call();
}

//小米Note
class MiNote implements Phone {
	public void call() {
		System.out.println("小米Note打电话");
	}
}

//红米
class RedMi implements Phone {
	public void call() {
		System.out.println("红米打电话");
	}
}

包和权限修饰符

包的概述

java的包,其实就是我们电脑系统中的文件夹,包里存放的是类文件。

当类文件很多的时候,通常我们会采用多个包进行存放管理他们,这种方式称为分包管理。

在项目中,将相同功能的类放到一个包中,方便管理。并且日常项目的分工也是以包作为边界。

包的声明格式

通常使用公司网址反写,可以有多层包,包名采用全部小写字母,多层包之间用”.”连接

类中包的声明格式:

package 包名.包名.包名…;

注意:声明包的语句,必须写在程序有效代码的第一行(注释不算)

案例代码-演示

/*
 * 包的特点:
 * 		可以有多层
 * 		不同包下的文件名可以重复
 * 		包的声明必须是第一行代码
 * 
 */
public class PackageDemo {

}

包之间互相访问

在访问类时,为了能够找到该类,必须使用含有包名的类全名(包名.类名)。

包名.包名….类名
如: java.util.Scanner
     java.util.Random
	cn.itcast.Demo
带有包的类,创建对象格式:包名.类名 变量名 = new包名.类名();
     cn.itcast.Demo d = new cn.itcast.Demo();

前提:包的访问与访问权限密切相关,这里以一般情况来说,即类用public修饰的情况。

类的简化访问

当要使用一个类时,这个类与当前程序在同一个包中(即同一个文件夹中),或者这个类是java.lang包中的类时通常可以省略掉包名,直接使用该类。

我们每次使用类时,都需要写很长的包名。很麻烦,我们可以通过import导包的方式来简化。

可以通过导包的方式使用该类,可以避免使用全类名编写(即,包类.类名)。

导包的格式:

import 包名.类名;

案例代码-包

package com.Package;

import java.util.ArrayList;

/*
 * 
 * 不同包之间的互相访问
 * 		使用类的全名
 * 		使用关键字import将类导入
 * 
 * 
 * 注意:*代表的是通配符,代表导入了这个包下所有的类,并没有导入子包下的类
 * 
 * 类的全名:包名.类名
 * 
 * 
 */

public class Demo {
	public static void main(String[] args) {
		// 相同包下的类可以直接访问,不需要做其他的操作
		// PackageDemo pd = new PackageDemo();

		java.util.ArrayList list = new java.util.ArrayList();

		ArrayList list2 = new ArrayList();
	}

}

权限修饰符

在Java中提供了四种访问权限,使用不同的访问权限时,被修饰的内容会有不同的访问权限,以下表来说明不同权限的访问能力:

 publicprotecteddefaultprivate
同一类中
同一包中(子类与无关类) 
不同包的子类  
不同包中的无关类   

归纳一下:在日常开发过程中,编写的类、方法、成员变量的访问

  • A:要想仅能在本类中访问使用private修饰
  • B:要想本包中的类都可以访问除了private修饰符,其它都可以
  • C:要想本包中的类与其他包中的子类可以访问使用protected修饰
  • D:要想所有包中的所有类都可以访问使用public修饰。 注意:如果类用public修饰,则类名必须与文件名相同。一个文件中只能有一个public修饰的类。

案例代码-修饰符

/*
 * 权限修饰符:
		public 当前类,相同包下不同的类,不同包下的类
		default 当前类,相同包下不同的类
		private 当前类
		protected 当前类,相同包下不同的类
		
		default:当前包下使用
		protected:让子类对象使用
 *  
 */
public class PermissionsDemo {
	
	public void publicMethod() {
		System.out.println("publicMethod");
	}
	
	void defaultMethod() {
		System.out.println("defaultMethod");
	}

	private void privateMethod() {
		System.out.println("privateMethod");
	}
	
	protected void protectedMethod() {
		System.out.println("protectedMethod");
	}
	
	public static void main(String[] args) {
		PermissionsDemo pd = new PermissionsDemo();
		pd.publicMethod();
		pd.defaultMethod();
		pd.privateMethod();
		pd.protectedMethod();
	}
}
public class PermissionsDemo2 {
	
	 
	
	public static void main(String[] args) {
		PermissionsDemo pd = new PermissionsDemo();
		pd.publicMethod();
		pd.defaultMethod();
		//pd.privateMethod();
		pd.protectedMethod();
	}
}
import com.itheima_02.PermissionsDemo;

public class PermissionsDemo3 {
	
	 
	
	public static void main(String[] args) {
		PermissionsDemo pd = new PermissionsDemo();
		pd.publicMethod();
		//pd.defaultMethod();
		//pd.privateMethod();
		//pd.protectedMethod();
	}
}
import com.itheima_02.PermissionsDemo;

public class PermissionsDemo4 extends PermissionsDemo {
	
	public void function() {
		super.publicMethod();
		super.protectedMethod();
	}
	 
	
	public static void main(String[] args) {
	
	}
}

修饰符总结

修饰符成员变量成员方法构造方法
publicYYYY
defaultYYYY
protected YYY
private YYY
abstractY Y 
static YY 
finalYYY 

内部类

1.1      内部类概述

A:什么是内部类

将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类。其他类也称为外部类。

B:什么时候使用内部类

在描述事物时,若一个事物内部还包含其他可能包含的事物,比如在描述汽车时,汽车中还包含这发动机,这时发动机就可以使用内部类来描述。

class 汽车 { //外部类
	class 发动机 { //内部类
}
}

成员内部类

成员内部类,定义在外部类中的成员位置。与类中的成员变量相似,可通过外部类对象进行访问

A:定义格式

class 外部类 { 
	修饰符 class 内部类 {
		//其他代码
}
}

B:访问方式

外部类名.内部类名 变量名 = new 外部类名().new 内部类名();

案例代码-内部类

package com.Package;

/*
 * 成员内部类:
 * 		在类的成员位置,和成员变量以及成员方法所在的位置是一样的
 * 		在内部类当中,可以直接访问外部类的成员,包括私有成员
 */

public class Demo2 {
	public static void main(String[] args) {
		// Outer o = new Outer();
		// o.method();

		Outer.Inner i = new Outer().new Inner();
		i.function();

	}
}

class Outer {
	private int num = 10;

	public void method() {
		Inner i = new Inner();
		i.function();
	}

	class Inner {
		public void function() {
			System.out.println(num);
		}
	}
}

成员内部类可以使用的修饰符:private,public,procted,final,static,abstract

案例代码-成员内部类修饰符

package com.Package;
/*
 * 成员内部类的修饰符:
 * 		我们可以使用权限修饰符修饰成员内部类,但是如果使用私有来修饰,则无法在其他类中访问
 * 		我们可以使用static修饰成员内部类,不用再创建外部类的对象了
 * 
 * 我们可以使用abstract,final修饰成员内部类
 */

public class Demo3 {
	public static void main(String[] args) {
		// Outer2.Inner2 i;

		// Outer2.Inner2 i = new Outer2.Inner2();
		// i.function();

		Outer2.Inner2.function();
	}
}

class Outer2 {
	public void method() {
		Inner2 i = new Inner2();
	}

	static class Inner2 {
		public static void function() {
			System.out.println("function");
		}
	}
}

局部内部类

 局部内部类,定义在外部类方法中的局部位置。与访问方法中的局部变量相似,可通过调用方法进行访问

A:定义格式

class 外部类 { 
	修饰符 返回值类型 方法名(参数) {
class 内部类 {
//其他代码
}
}
}

B:访问方式

在外部类方法中,创建内部类对象,进行访问

案例代码-局部内部类

package com.Package2;
/*
 * 局部内部类
 * 		在方法内,出了方法之后就无法使用
 * 		
 * 
 */
public class Demo {
	public static void main(String[] args) {
		Outer o = new Outer();
		o.method();
	}
}

class Outer {
	public void method() {
		int num = 10;
		
		class Inner {
			public void function() {
				System.out.println("function");
			}
		}
		
		Inner i = new Inner();
		i.function();
		
	}
	
	public void test() {
		//Inner i = new Inner();
		//System.out.println(num);
	}
}

匿名内部类

A:作用:匿名内部类是创建某个类型子类对象的快捷方式。 B:格式

new 父类或接口(){
	//进行方法重写
};

代码演示

//已经存在的父类:
public abstract class Person{
	public abstract void eat();
}
//定义并创建该父类的子类对象,并用多态的方式赋值给父类引用变量
Person  p = new Person(){
	public void eat() {
		System.out.println(“我吃了”);
}
};
//调用eat方法
p.eat();

使用匿名对象的方式,将定义子类与创建子类对象两个步骤由一个格式一次完成,。虽然是两个步骤,但是两个步骤是连在一起完成的。

匿名内部类如果不定义变量引用,则也是匿名对象。代码如下:

new Person(){
	public void eat() {
		System.out.println(“我吃了”);
}
}.eat();

案例代码-匿名内部类

package com.Package3;
/*
 * 匿名内部类:
 * 		可以把匿名内部类看成是一个没有名字的局部内部类
 * 		定义在方法当中
 * 		必须在定义匿名内部类的时候创建他的对象
 * 格式:
 * 		new 类/接口(){
 * 			如果是创建了继承这个类的子类对象,我们可以重写父类的方法
 * 			如果是创建了实现这个接口的子类对象,我们必须要实现该接口的所有方法
 * 		};
 * 原理:而是创建了继承这个类的子类对象或者是创建了实现这个接口的子类对象
 * 	
 */

public class Demo {
	public static void main(String[] args) {
		Outer o = new Outer();
		o.method();
	}
}

interface Inner {
	public void function();
}

class Outer {
	public void method() {

		/*
		 * new Inner() {
		 * 
		 * @Override public void function() { System.out.println("function"); }
		 * 
		 * }.function();;
		 */

		Inner i = new Inner() {

			@Override
			public void function() {
				System.out.println("function");
			}

		};

		i.function();
		i.function();

	}
}

案例代码-匿名内部类作为参数传递

package com.Package4;

public interface Animal {
	public abstract void eat();
}


package com.Package4;

public class Cat implements Animal {

	@Override
	public void eat() {
		System.out.println("猫吃鱼");
	}

}
package com.Package4;

public class Dog implements Animal {

	@Override
	public void eat() {
		System.out.println("狗啃骨头");
	}

}
package com.Package4;
/*
 * 匿名内部类的应用场景:
 * 		作为参数进行传递
 * 		
 *      
 */

public class Demo {
	public static void main(String[] args) {
		// method(new Dog());
		// method(new Cat());

		method(new Animal() {

			@Override
			public void eat() {
				System.out.println("猫吃鱼");
			}

		});
	}

	public static void method(Animal a) {
		a.eat();
	}
}