Java尚硅谷基础笔记-day7面向对象(三)

6.1 关键字:static

static关键字的使用:

1.static:静态的
2.static可以用来修饰:属性,方法,代码块,内部类
3.使用static修饰属性:静态变量

3.1属性按是否使用static修饰,又分为:静态属性VS非静态属性(实例变量) 实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其非静态属性时,不会导致其他对象中同样的属性值的修改。
静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量。其他对象调用此静态变量时,是修改过了的。
3.2static修饰属性的其他说明: 静态变量随着类的加载而加载。可以通过“类.静态变量”的方式进行调用 静态变量的加载要早于对象的创建 由于类只会加载一次,则静态变量在内存中也只会存在一份 类可以调用类变量,而对象可以嗲用类变量和实例变量。
3.3 静态属性举例:System.out;Math.PI;
4.使用static修饰方法:静态方法
4.1.随着类的加载而加载,可以通过“类.静态方法”的方式进行调用
4.2 类可以调用静态方法,对象可以调用静态方法和非静态方法
4.3 静态方法中,只能调用静态的方法和属性
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
5.static注意点:
5.1在静态方法内,不能使用this关键字,super关键字
5.2 从生命周期理解静态属性和静态方法
生命周期:类的加载,对象出生,对象消亡,类消亡
6.开发中,如何确定一个属性是否要声明为static
属性时可以被多个对象所共享的,不会随着对象的不同而不同
类中的常量也常常声明为static
开发中,如何确定一个方法是否要声明为static
操作静态属性的方法通常设置为static
工具类中的方法,习惯上声明为static,比如Math,Arrays,Collections

内存解析
在这里插入图片描述

public class Circle{
	private double radius;
	private int id;
	private static int total;
	private static int init=1001;
	public Circle() {
		id=init++;//自动赋值
		total++;
	}
	public Circle(double radius) {
		this();
		//id=init++;
		//total++;
		this.radius=radius;
	}		
	public static int getTotal() {
		return total;
	}
	public int getId() {
		return id;
	}
	public  double findArea() {
		return Math.PI*radius*radius;
	}
}
public class classTest1 {
	public static void main(String[] args) {
		Circle c1=new Circle();
		Circle c2=new Circle();
		Circle c3=new Circle();
		System.out.println(c1.getId());//1001
		System.out.println(c2.getId());//1002
		System.out.println(c3.getId());//1003
		System.out.println(Circle.getTotal());//3
	}
}

单例设计模式
在这里插入图片描述
单例设计模式
1.所谓类的单例设计模式,就是采取一定的方法保证在整个的系统软件中,对某个类只能存在一个对象实例
2.区分饿汉式和懒汉式
饿汉式:
坏处:对象加载时间过长
好处:饿汉式是线程安全的
懒汉式:
好处:延迟对象的创建
目前写法的坏处:线程不安全
单例模式的优点
由于单例模式只生成一个实例, 减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
饿汉式

public class classTest1 {
	public static void main(String[] args) {
		Bank bank1=Bank.getInstance();
		Bank bank2=Bank.getInstance();
		System.out.println(bank1==bank2);//true
	}
}
//饿汉式1
class Bank{
	//1.私有化类的构造器
	private Bank() {
		
	}
	//2.内部创建类的对象
	//4.要求此对象也必须声明为静态的
	private static Bank instance=new Bank();
	//public static final Bank instance=new Bank();
	//3.提供公共的静态的方法,返回类的对象
	public static Bank getInstance() {
		return instance;
	}
}
//饿汉式2
class Bank{
	//1.私有化类的构造器
	private Bank() {
		
	}
	//2.内部创建类的对象
	//4.要求此对象也必须声明为静态的
	private static Bank instance=null;
	static{
			instance=new Bank();
	}
	//3.提供公共的静态的方法,返回类的对象
	public static Bank getInstance() {
		return instance;
	}
}

懒汉式

public class classTest1 {
	public static void main(String[] args) {
		Order o1=Order.getInstance();
		Order o2=Order.getInstance();
		System.out.println(o1==o2);//true
	}
}
//懒汉式
class Order{
	//1.私有化类的构造器
	private Order() {
		
	}
	//2.内部创建类的对象,没有初始化
	//4.要求此对象也必须声明为静态的
	private static Order instance=null;
	//3.提供公共的静态的方法,返回类的对象
	public static Order getInstance() {
		if(instance==null) {
			instance=new Order();
		}
		return instance;
	}
}

6.2 理解main方法的语法

main()方法的使用说明
1.main()方法作为程序的入口
2.main()方法也可以是一个普通的静态方法
3.main()方法可以作为我们与控制台交互的方式

public class classTest1 {
	public static void main(String[] args) {
		Main.main(new String[100]);//main静态方法的调用
		classTest1 test=new classTest1 ();
		test.show();//调用非静态方法
	}
	public void show() {
		
	}
	
}
class Main{
	public static void main(String[] args) {
		for(int i=0;i<args.length;i++) {
			System.out.println(args[i]);
		}
	}
}
public class classTest1 {
	public static void main(String[] args) {//入口,传入string类型
		for(int i=0;i<args.length;i++) {
			System.out.println("******"+args[i]);
			int num=Integer.parseInt(args[i]);
			System.out.println("######"+num);
		}
	}
}

在这里插入图片描述
可以正常编译运行

6.3 类的成员之四:代码块

1.代码块的作用:用来初始化类,对象
2.代码块如果有修饰的话,只能使用static
3.静态代码块:

  • 内部可以有输出语句;
  • 随着类的加载而执行
  • 作用:初始化类的信息
  • 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
  • 静态代码块的执行要优先于非静态代码块的执行
  • 静态代码块内只能调用静态的属性,静态的方法,不能调用非静态的结构

4.非静态代码块:

  • 内部可以有输出语句;
  • 随着对象的创建而执行;
  • 每创建一个对象,就执行一次非静态代码块
  • 作用:可以在创建对象时,对对象的属性等进行初始化
  • 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
  • 非静态代码块内可以调用静态的属性,静态的方法,或非静态的属性,非静态的方法
public class BlockTest {
	public static void main(String[] args) {
		String desc=Person.desc;//hello,static block
		Person p1=new Person();//hello,block
		Person p2=new Person();//hello,block
	}
}
class Person{
	String name;
	int age;
	static String desc="我是一个人";
	public Person() {
		
	}
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	static {
		System.out.println("hello,static block");
	}
	{
		System.out.println("hello,block");
	}
	public void eat() {
		System.out.println("吃饭");
	}
}

对属性可以赋值的位置:
1.默认初始化
2.显式初始化/ 5.在代码块中赋值
3.构造器中的初始化
4.“对象.属性”或“对象.方法”的方式进行赋值

public class OrderTest {
	public static void main(String[] args) {
		Order o=new Order();
		System.out.println(o.orderId);//3
		//先写先执行
	}

}
class Order{
	{
		orderId=4;
	}
	int orderId=3;
}

class Root{
	static{
		System.out.println("Root的静态初始化块");
	}
	{
		System.out.println("Root的普通初始化块");
	}
	public Root(){
		System.out.println("Root的无参数的构造器");
	}
}
class Mid extends Root{
	static{
		System.out.println("Mid的静态初始化块");
	}
	{
		System.out.println("Mid的普通初始化块");
	}
	public Mid(){
		System.out.println("Mid的无参数的构造器");
	}
	public Mid(String msg){
		//通过this调用同一类中重载的构造器
		this();
		System.out.println("Mid的带参数构造器,其参数值:"
			+ msg);
	}
}
class Leaf extends Mid{
	static{
		System.out.println("Leaf的静态初始化块");
	}
	{
		System.out.println("Leaf的普通初始化块");
	}	
	public Leaf(){
		//通过super调用父类中有一个字符串参数的构造器
		super("尚硅谷");
		System.out.println("Leaf的构造器");
	}
}
public class LeafTest{
	public static void main(String[] args){
		new Leaf(); 
		//new Leaf();
	}
}
/*
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:尚硅谷
Leaf的普通初始化块
Leaf的构造器
*/
class Father {
	static {
		System.out.println("11111111111");
	}
	{
		System.out.println("22222222222");
	}

	public Father() {
		System.out.println("33333333333");

	}

}

public class Son extends Father {
	static {
		System.out.println("44444444444");
	}
	{
		System.out.println("55555555555");
	}
	public Son() {
		System.out.println("66666666666");
	}


	public static void main(String[] args) { // 由父及子 静态先行
		System.out.println("77777777777");
		System.out.println("************************");
		new Son();
		System.out.println("************************");

		new Son();
		System.out.println("************************");
		new Father();
	}
}
/*
11111111111
44444444444
77777777777
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
55555555555
66666666666
************************
22222222222
33333333333
*/

6.4 关键字:final

1.final可以用来修饰的结构:类,方法,变量
2.final 用来修饰一个类:此类不能被其他类所继承。
比如:String类,System,StringBuffer
3.final 用来修饰方法,表明此方法不可以被重写
比如:Object类中的getClass();
4.final 用来修饰变量,此时的变量就称为是一个常量

  • final 修饰属性,可以考虑赋值的位置有:显式初始化,代码块中的初始化,构造器中初始化
    (不可以用set等其他方法来赋值,构造器调用完之后final修饰的变量就在堆空间中出现了,此时必须赋值)
  • final修饰局部变量:尤其是使用final修饰形参时,表明此形参是一个常量(名称大写)。当我们调用此方法时,给常量形参赋一个实参,一旦以后,就只能在方法体内使用此形参,但不能进行重新赋值。
  • static final 用来修饰属性:全局常量
public class Something {
	public int addone(final int x) {
		//return ++x;错误
		return x+1;
	}

public class Something {
	public static void main(String[] args) {
		Other o=new Other();
		new Something().addone(o);
		}
	public void addone(final Other o) {
		//o=new Other();错误
		o.i++;
	}
}
class Other{
	public int i;
}

小结
public static void main(String[] args){方法体}

  • 权限修饰符:private 缺省 protected public–封装性
  • 修饰符:static final abstract native 可以用来修饰方法
  • 返回值类型:无返回值/有返回值–return
  • 方法名:需要满足标识符命名的规则,规范:“见名知意”
  • 形参列表:重载VS重写:参数的值传递机制:体现对象的多态性
  • 方法体:来体现方法的功能

6.5 抽象类与抽象方法

abstract关键字的使用
1.可以用来修饰的结构:类,方法
2.abstract修饰类:抽象类

  • 此类不能实例化
  • 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
  • 开发中,都会提供抽象类的方法,让子类对象实例化,完成相关操作
    3.abstract修饰方法:抽象方法
  • 抽象方法只有方法的声明,没有方法体
  • 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
  • 若子类重写了父类中的所有的抽象方法后,此子类方可实例化
  • 若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰。
    abstract使用上的注意点:
  • abstract不能用来修饰属性,构造器等
  • abstract不能用来修饰私有方法,静态方法,final的方法,final的类。不能继承
    静态方法要通过类来调用,有具体的实现,而abstract的方法需要重写,没有具体的实现
    多态的意义也体现在抽象类,本身抽象类不能创建对象,如果不使用多态抽象类就没有意义。
public abstract class GeometricObject {
	String color="white";	
	public GeometricObject(String color) {
		super();
		this.color = color;
	}

	public abstract double findArea();
}

public class Cylinder extends GeometricObject{
	double width;
	double height;

	public Cylinder(double width,double height,String color) {
		super(color);
		this.width=width;
		this.height=height;
	}
	@Override
	public double findArea() {//表面积
		return width*height;
	}
}

在这里插入图片描述
问题1:final不能继承,而抽象类需要继承
问题2:可以定义构造器,便于子类实例化调用
问题3:可以这样理解
匿名类
非匿名类非匿名对象
匿名对象
匿名子类的对象
匿名子类的匿名对象

public class PersonTest {
	public static void main(String[] args) {
		Student s=new Student();
		method(s);//非匿名的类非匿名的对象
		method(new Student());//非匿名的类匿名的对象
		//匿名子类的对象P
		Person p=new Person() {
			@Override
			public void eat() {	
			}
			@Override
			public void walk() {	
			}	
		};
		//匿名子类的匿名对象
		method(new Person() {
			@Override
			public void eat() {	
			}
			@Override
			public void walk() {	
			}	
		});
	}
	public static void method(Person p) {
		p.eat();
		p.walk();
	}
}
abstract class Person{
	String name;
	int age;	
	public Person() {
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public abstract void eat();
	public abstract void walk();
}
class Student extends Person{
	String course;	
	public Student() {
		super();
	}
	public Student(String name, int age, String course) {
		super(name, age);
		this.course = course;
	}
	@Override
	public void eat() {
		
	}
	@Override
	public void walk() {
		
	}
}

多态的应用:模板方法设计模式
在这里插入图片描述
举例
代码运行时间

public class Something {
	public static void main(String[] args) {
		SubTemplate t=new SubTemplate();
		t.spendTime();
	}
}
abstract class Template{
	public void spendTime() {
		long start=System.currentTimeMillis();
		code();
		long end=System.currentTimeMillis();
		System.out.println("花费的时间为:"+(end-start));
	}
	public abstract void code();
}
class SubTemplate extends Template{
	@Override
	public void code() {
		for(int i=2;i<=1000;i++) {
			boolean isFlag=true;
			for(int j=2;j<=Math.sqrt(i);j++) {
				if(i%j==0) {
					isFlag=false;
					break;
				}
			}
			if(isFlag==true) {
				System.out.println(i);
			}
		}
		
	}
}
public class TemplateMethodTest {

	public static void main(String[] args) {
		BankTemplateMethod btm = new DrawMoney();
		btm.process();

		BankTemplateMethod btm2 = new ManageMoney();
		btm2.process();
	}
}
abstract class BankTemplateMethod {
	// 具体方法
	public void takeNumber() {
		System.out.println("取号排队");
	}

	public abstract void transact(); // 办理具体的业务 //钩子方法

	public void evaluate() {
		System.out.println("反馈评分");
	}

	// 模板方法,把基本操作组合到一起,子类一般不能重写
	public final void process() {
		this.takeNumber();

		this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码

		this.evaluate();
	}
}

class DrawMoney extends BankTemplateMethod {
	public void transact() {
		System.out.println("我要取款!!!");
	}
}

class ManageMoney extends BankTemplateMethod {
	public void transact() {
		System.out.println("我要理财!我这里有2000万美元!!");
	}
}

练习
在这里插入图片描述
在这里插入图片描述

public class PayrollSystem {
	public static void main(String[] args) {
		/*
		Scanner scanner=new Scanner(System.in);
		System.out.println("请输入当月的月份:");
		int month=scanner.nextInt();
		*/
		Calendar calendar=Calendar.getInstance();
		int month=calendar.get(Calendar.MONTH);//从0开始
		Employee[] e=new Employee[2];
		e[0]=new SalariedEmployee("曼森",new MyDate(1992,2,18),1002,10000);
		e[1]=new HourlyEmployee("潘玉生",new MyDate(1993,7,4),2001,60,240);
		for(int i=0;i<e.length;i++) {
			System.out.println(e[i]);
			double salary=e[i].earnings();
			System.out.println(salary);
			if((month+1)==e[i].getBirthday().getMonth()) {
				System.out.println("生日快乐!");
			}
		}
	}

}
abstract class Employee{
	private String name;
	private MyDate birthday;
	private int number;

	public abstract double earnings();

	public Employee(String name, MyDate birthday, int number) {
		super();
		this.name = name;
		this.birthday = birthday;
		this.number = number;
	}
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return "[name=" + name + ", birthday=" + birthday + ", number=" + number + "]";
	}

	public MyDate getBirthday() {
		return birthday;
	}

	public int getNumber() {
		return number;
	}
	
	
}
class MyDate{
	private int year;
	private int month;
	private int day;	
	public MyDate(int year, int month, int day) {
		super();
		this.year = year;
		this.month = month;
		this.day = day;
	}
	

	public int getYear() {
		return year;
	}


	public int getMonth() {
		return month;
	}


	public int getDay() {
		return day;
	}


	@Override
	public String toString() {
		return year + "年" + month + "月" + day + "日";
	}
	
}
class SalariedEmployee extends Employee{

	private double monthlySalary;

	public SalariedEmployee(String name, MyDate birthday, int number, double monthlySalary) {
		super(name, birthday, number);
		this.monthlySalary = monthlySalary;
	}
	@Override
	public double earnings() {
		// TODO Auto-generated method stub
		return monthlySalary;		
	}
	@Override
	public String toString() {
		return "SalariedEmployee" + super.toString();
	}	
}
class HourlyEmployee extends Employee{
	private double wage;
	private double hour;	
	public HourlyEmployee(String name, MyDate birthday, int number, double wage, double hour) {
		super(name, birthday, number);
		this.wage = wage;
		this.hour = hour;
	}
	
	@Override
	public double earnings() {
		return wage*hour;
	}
	public String toString() {
		return "HourlyEmployee" + super.toString();
	}
}

6.6 接口

接口的使用
1.接口使用interface来定义
2.Java中,接口和类是并列的两个结构
3.如何定义接口:定义接口中的成员

  • JDK7及以前,只能定义全局常量抽象方法
  • 全局变量:public static final的,但是书写时,可以省略不写
  • 抽象方法:public abstract的
  • JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法,默认方法
    4.接口中不能定义构造器的!意味着接口不可以实例化
    5.java开发中,接口通过(implements)的方式来使用
  • 如果实现类覆盖了接口(间接和直接父类接口)中的所有抽象方法,则此类可以实例化
  • 如果实现类没有覆盖接口中的所有抽象方法,则此实现类是一个抽象类
    6.java类可以实现多个接口—弥补了java单继承性的局限性
    格式:class AA extends BB implements CC,DD…
    7.接口与接口之间可以继承,而且可以多继承
    8.接口的具体使用,体现多态性
    9.接口,实际上可以看成是一种规范
    继承是“是不是”的关系,接口是“能不能”的关系
interface Flyable{
	//全局常量
	public static final int MAX_SPEED=7900;
	int MIN_SPEED=1;//省略了public static final
	//抽象方法
	public abstract void fly();
	void stop();//省略了public abstract
}
class Plane implements Flyable{
	@Override
	public void fly() {
		
	}
	@Override
	public void stop() {
		
	}
}

接口中的匿名对象,匿名类

public class test1{
	public static void main(String[] args) {
		//1.创建了接口的非匿名实现类的非匿名对象
		Plane p=new Plane();
		method(p);
		//2.创建了接口的非匿名实现类的匿名对象
		method(new Plane());
		//3.创建了接口的匿名实现类的非匿名对象
		Flyable f=new Flyable() {
			@Override
			public void fly() {
				
			}
			@Override
			public void stop() {
				
			}
		};
		//4.创建了接口的匿名实现类的匿名对象
		method(new Flyable() {
			@Override
			public void fly() {
				
			}
			@Override
			public void stop() {
				
			}
		});
	}
	public static void method(Flyable f) {
		
	}
}

接口的应用:代理模式
在这里插入图片描述

public class test1 {
	public static void main(String[] args) {
		Network net = new ProxyServer(new RealServer());
		net.browse();
	}
}

interface Network {
	public void browse();
}

// 被代理类
class RealServer implements Network {
	@Override
	public void browse() {
		System.out.println("真实服务器上网浏览信息");
	}
}

// 代理类
class ProxyServer implements Network {
	private Network network;

	public ProxyServer(Network network) {
		this.network = network;
	}

	public void check() {
		System.out.println("检查网络连接等操作");
	}

	public void browse() {
		check();
		network.browse();
	}
}

public class StaticProxyTest {

	public static void main(String[] args) {
		Star s = new Proxy(new RealStar());
		s.confer();
		s.signContract();
		s.bookTicket();
		s.sing();
		s.collectMoney();
	}
}

interface Star {
	void confer();// 面谈

	void signContract();// 签合同

	void bookTicket();// 订票

	void sing();// 唱歌

	void collectMoney();// 收钱
}
//被代理类
class RealStar implements Star {

	public void confer() {
	}

	public void signContract() {
	}

	public void bookTicket() {
	}

	public void sing() {
		System.out.println("明星:歌唱~~~");
	}

	public void collectMoney() {
	}
}
//代理类
class Proxy implements Star {
	private Star real;

	public Proxy(Star real) {
		this.real = real;
	}

	public void confer() {
		System.out.println("经纪人面谈");
	}

	public void signContract() {
		System.out.println("经纪人签合同");
	}

	public void bookTicket() {
		System.out.println("经纪人订票");
	}

	public void sing() {
		real.sing();
	}

	public void collectMoney() {
		System.out.println("经纪人收钱");
	}
}

在这里插入图片描述
相同点:不能实例化;都可以包含抽象方法
不同点:1.把抽象类和接口(java7,8,9)的定义,内部结构解释说明
2.类:单继承 接口:多继承
类与接口:多实现
面试题:排错
x不明确

System.out.println(super.x);
System.out.println(A.x);

在这里插入图片描述
排错:

ball = new Ball("Football");
//接口中的ball为常量不能再new

在这里插入图片描述
练习
在这里插入图片描述
方法一

public class InterfaceTest {
	public static void main(String[] args) {
		CompareCircle c1=new CompareCircle(2.3);
		CompareCircle c2=new CompareCircle(3.4);
		int compareValue=c1.compareTo(c2);
		if(compareValue>0) {
			System.out.println("c1对象大");
		}else if(compareValue<0) {
			System.out.println("c2对象大");
		}else {System.out.println("一样大");}
	}
}
interface CompareObject{
	public int compareTo(Object o);
}
class Circle{
	private double radius;
	
	public Circle(double radius) {
		super();
		this.radius = radius;
	}

	public double getRadius() {
		return radius;
	}

	public void setRadius(double radius) {
		this.radius = radius;
	}	
}
class CompareCircle extends Circle implements CompareObject{
	public CompareCircle(double radius) {
		super(radius);
	}
	@Override
	public int compareTo(Object o) {
		if(this==o) {
			return 0;
		}
		if(o instanceof CompareCircle) {
			CompareCircle c=(CompareCircle) o;
			if(this.getRadius()>c.getRadius()) {
				return 1;
			}
			if(this.getRadius()<c.getRadius()) {
				return -1;
			}else {
				return 0;
			}
		}else {return 0;}
	}
}

方法二
将radius定义为Double包装类
调用包装类中的compareTo方法

class Circle{
	private Double radius;
	
	public Circle(Double radius) {
		super();
		this.radius = radius;
	}

	public Double getRadius() {
		return radius;
	}

	public void setRadius(Double radius) {
		this.radius = radius;
	}	
}
class CompareCircle extends Circle implements CompareObject{
	public CompareCircle(Double radius) {
		super(radius);
	}
	@Override
	public int compareTo(Object o) {
		if(this==o) {
			return 0;
		}
		if(o instanceof CompareCircle) {
			CompareCircle c=(CompareCircle) o;
			return this.getRadius().compareTo(c.getRadius());
		}
		
			
		else {return 0;}

		
	}
}

java8接口新特性
静态方法,默认方法

public class test1 {
	public static void main(String[] args) {
		SubClass s=new SubClass();
		//s.method1(); error
		//SubClass.method1(); error
		//知识点1:接口中定义的静态方法,只能通过接口来调用
		CompareA.method1();
		//知识点2:通过实现类的对象,可以调用接口中的默认方法
		//如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
		s.method2();
		//SubClass.method2(); error
		//知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法
		//那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法
		//类优先原则
		s.method3();//Superclass:西安
		//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法
		//那么在实现类没有重写此方法的情况下,报错----接口冲突
		//这就需要我们必须在实现类中重写此方法
	}
}

interface CompareA {
	double PI = 3.14;
	public static void method1() {
		System.out.println("compareA:北京");
	}
	public default void method2() {
		System.out.println("compareA:上海");
	}

	default void method3() {
		System.out.println("compareA:西安");
	}
}
class Superclass{
	public void method3() {
		System.out.println("Superclass:西安");
	}
}
class SubClass extends Superclass implements CompareA{
	
}
interface CompareB {
	default void method3() {
		System.out.println("compareB:西安");
	}
} 
class SubClass extends Superclass implements CompareA,CompareB{
	@Override
	public void method3() {
		System.out.println("SubClass:西安");
	}
	//知识点5:如何在子类(实现类)的方法中调用父类,接口中被重写的方法
	public void myMethod() {
		method3();//调用自己定义的重写的方法
		super.method3();//调用的是父类中声明的
		//调用接口中的默认方法
		CompareA.super.method3();
		CompareB.super.method3();
	}
}

6.7 类的成员之五:内部类

内部类
1.java中允许将一个类A声明在另一个类B中,则leiA就是内部类,类B称为外部类
2.内部类的分类:成员内部类(静态,非静态)VS局部内部类(方法内,代码块内,构造器内)
3.成员内部类

  • 作为外部类的成员
  • 可以调用外部类的结构
  • 可以被static修饰
  • 可以被4中不同的权限修饰
  • 作为一个类:
  • 类内可以定义属性,方法,构造器等
  • 可以被final修饰,表示此类不能被继承。
  • 可以被abstract修饰
    4.关注的问题:
  • 如何实例化成员内部类的对象
  • 如何在成员内部类中区分调用外部类的结构
  • 开发中局部内部类的使用

实例化成员内部类的对象

public class test1 {
	public static void main(String[] args) {
		//静态成员内部类,创建实例
		Person.Dog dog=new Person.Dog();
		dog.show();
		//非静态成员内部类,创建实例
		//Person.Bird bird=new Person.Bird();
		Person p=new Person();
		Person.Bird bird=p.new Bird();
	}
}

class Person{
	//静态成员内部类
	static class Dog{
		public void show() {
			
		}
	}
	//非静态成员内部类
	class Bird{
		public void sing() {
			System.out.println("我是一只小鸟");
			Person.this.eat();//外部类的方法
		}
	}
	public void eat() {
		
	}
	public void method() {
		//局部内部类
		class AA{
			
		}
	}
	{
		//局部内部类
		class BB{
			
		}
	}
}
public class test1 {
	public static void main(String[] args) {
		Test t = new Test();//5
		Test.Inner r = t.new Inner();
		System.out.println(r.a);//5
	}
	
}

class Test {
	public Test() {
		Inner s1 = new Inner();
		s1.a = 10;
		Inner s2 = new Inner();
		s2.a = 20;
		Test.Inner s3 = new Test.Inner();
		System.out.println(s3.a);
	}

	class Inner {
		public int a = 5;
	}
}

成员内部类中区分调用外部类的结构

public class test1 {
	public static void main(String[] args) {
		Outer a = new Outer();
		Outer.Inner b = a.new Inner();
		b.mb(333);
	}
}

class Outer {
	private int s = 111;

	public class Inner {
		private int s = 222;

		public void mb(int s) {
			System.out.println(s); // 局部变量s
			System.out.println(this.s); // 内部类对象的属性s
			System.out.println(Outer.this.s); // 外部类对象属性s
		}
	}
}
/*
333
222
111
*/

开发中局部内部类的使用
在局部内部类的方法中(比如:show)如果调用局部内部类所声明的方法(method)中的局部变量(比如num)要求此局部变量声明为final。(java8以后,可以省略final的声明)

public void method(){
	int num=10;
	class AA{
		public void show(){
		//num=20;
		System.out.println(num);
		}
	}
}

这是因为内部类和外部类声明为两个字节码文件,内部类调用num时,是调用的副本,所以能够调用却不能修改。
匿名内部类

interface Product{
	public double getPrice();
	public String getName();
}
public class AnonymousTest{
	public void test(Product p){
		System.out.println("购买了一个" + p.getName() + ",花掉了" + p.getPrice());
	}
	public static void main(String[] args) {
		AnonymousTest ta = new AnonymousTest();
		//调用test方法时,需要传入一个Product参数,
		//此处传入其匿名实现类的实例
		ta.test(new Product(){
			public double getPrice(){
				return 567.8;
			}
			public String getName(){
				return "AGP显卡";
			}
		});
	}
}
//购买了一个AGP显卡,花掉了567.8

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值