Java面向对象的相关笔记

面向对象

面向对象的三大特性:

1.封装
2.继承
3.多态

类与对象的概念(定义类,创建对象)(类=属性+方法)

类是对象具有共性事物的抽象描述,是在概念上的一个定义。
例如:假设把一个班级看做成一个类,那么班级中的任一一个同学为一个对象(对象是实际存在的个体)
类–>对象-----实例化的过程
对象–>类-----抽象的过程
对象和对象之间具有共同特征,但是每个特征所对应的具体值不一样

面向对象可以分为三个阶段
OOA(面向对象的分析)
OOD(面向对象的设计)
OOP(面向对象的编程)

对象的创建和使用

在Java语言中,所有new出来的东西,统一放在堆(heap)中存储,无法直接对堆中数据进行访问,但可以通过引用来间接访问
引用保存的是内存地址,指向堆中的对象

//对象的创建和使用
public class OOTest01 {
	public static void main(String[] args) {
		//1.创建对象
		//stu1是一个局部变量,这个局部变量stu1是Student类型,也就是一个引用类型
		//stu1该局部变量称作引用,引用中保存的对象在堆中的内存地址
		//通过“引用”去间接访问堆中的对象
		Student stu1=new Student();
		
		//一个类可以创建多个对象
		//Student stu2=new Student();
		
		//2.使用对象
		//访问成员变量必须使用“引用.”
		
		//赋值
		stu1.id=15;
		stu1.name="熊大";
		stu1.age=60”;
		
		//读取过程
		System.out.println("id="+stu1.id);
		System.out.println("name="+stu1.name);
		System.out.println("age="+stu1.age);

在这里插入图片描述

面向对象的封装性

面向对象的封装性指的是:
1.属性私有化(属性前有private关键字)
2.对外提供公开的setter and getter方法(set\get+属性名,属性名首字母大写)

创建Customer类

public class Customer{
	//属性
	private int age;//成员变量,实例变量,非静态变量
	
	//set赋值
	public void setAge(int _age){
		if(_age<0){
			System.out.println("年龄不合法");
				return;
		}
		age=_age;
	}
	
	//get 读取
	public int getAge(){ //成员方法必须使用引用.方式调用
		return age;
	}
}

测试

public class Test{
	public static void main(String[] args){
		//创建Customer对象
		Customer c=new Customer();
		//赋值
		c.setAge(10);
		//读取
		System.out.println(c.getAge());
	}
}

构造函数(构造方法,构造器,Constructor)

构造方法主要用来创建类的实例化对象,可以完成创建实例化对象的初始化工作,声明格式:
构造方法修饰词列表 类名 (方法参数列表)

关于java类的构造函数:

1.构造方法语法:
[修饰符列表] 构造方法名 (形式参数列表){
方法体;
}

2.构造方法的作用:
第一:创建对象
第二:给成员变量赋值(初始化成员变量)

3.构造方法如何调用?
new 构造方法名(实参); 在堆中开辟空间存储对象

4.成员变量到底什么时候赋值?
只有在调用构造方法的时候,才会给成员变量赋值

构造方法修饰词列表:public proteced private
(类的构造方法和普通方法一样可以进行重载)

构造方法的特点

1.构造方法名必须和类名一致
2.构造方法不具有任何返回值类型,即没有返回值,关键字void也不能加入,加入了就不是构造方法了,变成了普通方法
3.任何类都有构造方法,如果没有显示类的定义,系统会默认为该类定义一个默认的无参数构造器,如果显示定义了构造器,系统就不会创建默认的无参数的构造器了

定义一个User类

public class User{
	//成员变量,属性,实例变量,非静态变量
	String name;
	int age;
	
	//构造方法
	User(){}
	User(int _age){
		age=_age;
	}

	User(String _name){
		name = _name;	
	}
	
	User(String _name,int _age){
		name = _name;
		age=_age;
	}
}

测试

public class Test{
	public static void main(){
		//创建User对象
		User u1=new User();
		User u2=new User(20);
		User u3=new User("熊大");
		User u4=new User("熊二"16);
	
		System.out.println(u2.age);
		System.out.println(u3.name);
		System.out.println(u4.name);
		System.out.println(u4.age);	
	}
}
Java中内存的划分

在这里插入图片描述

this关键字

1.this是什么?
this是一个引用类型,在堆中每一个Java对象都有this,this保存的内存地址指向自身。this 关键字用来表示当前对象本身,或当前类的一个实例,通过this可以调用对象的所有方法和属性。

2.this可以用在哪些地方?
this可以用在成员方法中
this可以用在构造方法中
语法:this(实参);
必须出现在构造方法第一行
通过一个构造方法区调用另一个构造方法,达到代码重用。

this不可以用在静态方法中

this用在成员方法中

public class This01{
	public static void main(String[] args){
		Employee e=new Employee(6632,"小狗");
		e.work();
		Employee e1=new Employee(2580,"猫仔");
		e1.work();
	}
}

class Employee{
	//Field
	int empno;
	String name;
	
	//Constructor
	Employee(){}
	Employee(int _empno,String _ename){
		empno=_empno;
		ename=_ename;
	}
	//this用在成员方法中,谁去调用这个成员方法,this就代表谁,this指的就是当前对象
	public void work(){
		System.out.println(this.ename+"在工作");//this.可以省略
	}
}

this用在构造方法中

public class This02{
	public static void main(String[] args){
		MyDate t=new MyDate();
		System.out.println(t.year+"年"+t.month+"月"+t.day+"日");
	}
}

//日期
class MyDate{
	//Field
	int year;
	int month;
	int day;
	//Constructor
	MyDate(){
		this(2000,2,2);
	}

	MyDate(int _year,int _month,int _day){
		year=_year;
		month=_month;
		day=_day;
	}
}

this可以用来区分成员变量和局部变量

public class This03{
	public static void main(String[] args){
		Manager m1=new Manager("熊大");
		Manager m2=new Manager();
		m2.setName("熊二");
		
		System.out.println(m1.getName());
		System.out.println(m2.getName());
	}
}

class Manager{
	//Field
	private String name;
	//Constructor
	Manager(){}
	Manager(String name){
		this.name=name;
	}
	
	public void setName(String name){
		this.name=name;
	}
	public String getName(){
		return name;//this.省略
	}
}

static关键字

1.static修饰的变量叫做静态变量
2.static修饰的方法叫做静态方法
3.static还可以定义静态语句块

演示static定义静态语句块

public class StaticTest01{
	//静态语句块
	//static定义的语句块在类加载阶段执行(在main方法执行之前),并且只执行一次,
	//按照自上而下的顺序执行
	static{
	System.out.println("今天");
	}
	static{
	System.out.println("你");
	}
	static{
	System.out.println("学废了么");
	}
	
	public static void main(String[] args){
		System.out.println("main方法执行");
	}
}

演示实例语句块
1.每一次调用构造方法之前会执行一次
2.自上而下的顺序执行
以下代码的输出顺序为:
A
1
2
Test无参数构造方法执行

public class Test{
 	//静态语句块
 	static{
		System.out.println("A");	
	}
	//实例语句块
	{
		System.out.println("1);
	}

	{
		System.out.println("2);
	}
	
	//Constructor
	Test(){
		System.out.println("Test无参数构造方法执行");
	}

	public static void main(String[] args){
		//调用构造方法
		new Test();
	}
}

演示static修饰的静态方法

public class Test{
	//成员方法
	//成员方法必须使用“引用.”方式调用
	/public void m1(){}

	//静态方法
	//可以使用“类名.”方式调用,也可以使用“引用.”,即使是“引用.”,底层还是类名.
	//静态方法中不能直接访问非静态数据
	//静态方法中不能使用this
	public static void m2(){
		System.out.println("m2..")}

	public static void main(String[] args){
		Test t= new Test();
		t.m1();
		
		m2();
		
		//静态方法正规的方式访问是“类名.”
		//静态方法也能用“引用.”访问
		t.m2();//编译阶段检查出t是Test类型,编译通过
		//运行的时候,仍然使用Test.方式访问,该方法不需要对象
	}
}

演示static修饰静态变量
什么时候变量声明成静态变量?
如果该属性所有的对象都有,并且这个属性的值是相同的,则该属性声明成静态变量(在类加载阶段赋值,并且只赋值一次)

public class Test{
	public static void main(Striong[] args){
		Animal a1=new Animal("猫",10);
		Animal a2=new Animal("狗",20);
		System.out.println(Animal.type);
	
		Animal a3=null;
		System.out.println(a3.type);//静态变量底层访问的时候一定使用 类名. 和对象无关,
									//不会出现空指针异常
	}
}

class Animal{
	//Field
	//成员变量(一个对象一份)
	//成员变量在创建对象的时候初始化,并且存储在堆中的每一个对象中
	String name;
	int age;

	//静态变量,被存储在方法区
	//所有的Java对象共享这一份
	//静态变量是类级别的,使用“类名.”方式访问
	Static String type = "陆生";

	//Constructor
	Animal(String name,int age){
		this.name = name;
		this.age = age;
	}
}

单例模式

什么是设计模式:设计模式是可以重复利用的解决方案。由GoF四人组在1995年提出。

设计模式分为三类:
1.创建型
2.结构性
3.行为型

单例模式的好处:
我们知道对象实例创建完成后,会放到堆中,如果堆中的实例过多,将会存在特别多的垃圾,这样会导致内存溢出等问题。使用单例模式后,只会创建一个实例,显著减少对象实例的个数,同时也会提高性能。

单例模式的缺点:单例模式的类型无法被继承。

单例模式纲领
1.构造方法私有化
2.对外提供一个公开的静态的获取当前类型对象的方法
3.提供一个当前类型的静态变量

单例模式分为两种:
1.饿汉式单例:(在类加载阶段就创建了对象)
2.懒汉式单例:(用到对象的时候才会创建对象)

实现懒汉式单例

public class Singleton{
	//静态变量
	private static Singleton s;
	//将构造方法私有化
	private Singleton(){}
	//对外提供一个公开获取Singleton对象的方法
	public static Singleton getInstance(){
		if(s==null){
		s=new Singleton();
		}
		return s;
	}
}

实现饿汉式单例

public class Customer{
	//类加载时只执行一次
	private static Customer c = new Customer();
	//构造方法私有化
	private Customer(){}
	//提供公开的方法
	public static Customer getInstance(){
		return c;
	} 
}

测试

public class Test{
	public static void main(String[] args){
		Customer c1=Customer.getInstance();
		Customer c2=Customer.getInstance();
		System.out.println(c1==c2);//true
	}
}

继承(类与类只支持单继承)

继承最基本作用:代码重用
继承最重要的作用:方法可以重写
语法:
[修饰符列表] class 子类名 extends 父类名{
类体
}
一个类如果没有显示继承其他类,则默认继承Object类

父类

public class Dad{
	public void study(){
		System.out.println("学习");
	}
	public void feed(){
		System.out.println("吃饭");
	}
}

子类

public class Son extends Dad{
	//所有父类的方法都可以继承过来
	//该子类包含父类中的study()和feed()方法
	public void sleep(){
	System.out.println("睡觉");
	Son.study();
	Son.feed();
	}	
}

有关于方法

什么是方法?
方法就是一段代码片段,调用的时候可以重复利用。

定义方法的语法
[方法的修饰符列表] 方法的返回值类型 方法名 (方法的形式参数列表){
java语句;
}

1.[方法的修饰符列表] 是可选项
2.方法的返回值类型,可以实java语言中的任何一种数据类型(基本数据类型和引用数据类型)
3.如果该方法执行结束之后,并没有任何返回值,那么定义方法的时候,返回值类型写:void
4.方法名只要是合法的标识符即可
5.方法的形式参数列表,可以有参数,也可以没有参数,如果有多个参数列表的话,使用 , 隔开
6.如果一个方法的返回值类型不是void,那么在方法体中必须使用return语句来返回数据。

关于方法的调用(在static中使用类名. 的方式去调用)
public class MethodTest02 {

	//入口
	public static void main(String[] args) {
		
	//在main方法中对sumInt方法进行调用,完成功能。
	//注意:加有static的方法,调用的时候必须采用“类名”的方式调用。
	
	MethodTest02.sumInt(10,20);
	MethodTest02.sumInt(50,100);
	
	}
	
	//定义方法,完成两个整数的求和。
	//注意:目前所有的方法定义成public static.
	public static void sumInt(int a,int b) {
		int c = a + b;
		System.out.println(a + "+" + b  + "=" + c);
	}
}

public class MethodTest03 {
	
	//入口
	public static void main(String[] args) {
	
		//方法调用
		MethodTest03.m1(13,15);
		MethodTest03.m2();
		//调用m3
		int retValue = MethodTest03.m3(100, 200);
		System.out.println("计算结果是:"+retValue);
	}
	
	//方法的定义
	//方法形式参数列表中起决定性作用的是参数的类型。
	//参数的名字(局部变量的名字)是随意的只要是合法的标识符即可。
	public static void println(String msg) {//String msg是方法的形式参数列表。
		System.out.println(msg);
	}
	
	public static void m1(int a, int b) {
		System.out.println(a+"+"+b+"="+(a+b));
		
	}
	
	public static void m2() {
		System.out.println("呵呵");
	}
	
	//该方法有返回值,程序必须使用return语句返回值 
	public static int m3(int a,int b) {
		
		int c=a+b;
		return c;//程序执行到此处m3方法执行结束
		
		//return语句下面不能再有其他代码,因为根本无法执行到。
		//System.out.println("ABC");//编译无法通过。
	}
	}
	
在调用方法时省去类名(在调用方法时,如果在当前类可以省去类名)
public class MethodTest04 {
	
	public static void main(String[] args) {
		A.m1();
		
		//Error:在当前类名中没有m1方法。
		//m1();
		
		MethodTest04.m2();
	
	//前提:在当前类名中可以省
	//类名可以省	
	m2();
	}

	public static void m2() {
		System.out.println("m2...");
	}
}

class A{
	
	public static void m1() {
		System.out.println("A's m1 method invoke!");
		
	}
}

关于方法的重载(overload)

优点:
1.记忆更少的方法名,方便调用
2.代码更加美观

重载时需要的条件:
1.发生在同一个类中
2.方法名相同
3.参数列表不同(参数的类型、个数、顺序)
4.和返回值类型无关
5.和方法的修饰符列表无关

public class MethodTest08 {
	public static void main(String[] args) {
			
			System.out.println(Computes.sum(10,20));
			
			System.out.println(Computes.sum(1.0,2.0));
			
			System.out.println(Computes.sum(10L,20L));
			
		}

	public static void m1(int a) {}
	public static void m1(double a) {}

	public static void m2(int a,int b) {}
	public static void m2(int a) {}
	
	public static void m3(int a,double b) {}
	public static void m3(double a,int b) {}
	
	//以下两个m4方法并没有构成重载
	//方法重复,错误的
	//public static void m4(int a){}
	//public static void m4(int b){}

	//方法的重载和方法的返回值类型无关
	 /* 
	public static void m5() {}
	public static void m5() {
		return 100;
	}
	*/	
	
	//方法的重载和方法的修饰符列表无关
	/*
	static void m6(){}
	public static void m6(){}
	*/
	}
	
class Computes{
		
	public static int sum(int a,int b) {
			
			return a + b;
			
		}
		
	public static double sum(double a,double b) {
			
			return a + b;
			
		}

	public static long sum(long a,long b) {
		
	return a + b;
		

		}
}
关于方法的递归(方法的递归调用就是方法自身调用自身)

以下程序因为递归没有结束条件,所以一直压线,没有弹栈,导致栈内存中溢出错误!


public class RecursionTest01 {

	//入口
	public static void main(String[] args) {
		
		m1();
	}

	public static void m1() {
		m1();//java.lang.StackOverflowError
	}
}

方法的覆盖(override)

1.什么时候进行方法的重写?
如果父类中的方法已经无法满足当前子类的业务需求,需要将父类中的方法重写

2.子类如果重写父类中的方法之后,子类对象一定调用的时重写之后的方法

3.发生在方法覆盖的条件:
第一:发生在具有继承关系的两个类之间
第二:必须具有相同的方法名,相同的返回值类型,相同的参数列表
第三:重写的方法不能比被重写的方法拥有更低的访问权限
第四:重写的方法不能比被重写的方法抛出更宽泛的异常
第五:私有的方法不能被覆盖
第六:构造方法不存在覆盖
第七:静态方法不存在覆盖
第八:覆盖指的是成员方法,和成员变量无关

public class Test{
	public static void main(String[] args){
		//创建子类对象
		Cat c=new Cat();
		//调用方法
		c.move();

		Animal a=new Animal();
		a.move();
	}
}

//父类
class Animal{
	//成员方法
	public void move(){
		System.out.println("动物在移动");
		}
}

//子类
class Cat extends Animal{
	//Cat的move方法应该输出:猫在移动
	//Animal中的move方法已经无法满足需求
	//在Cat类堆move方法进行重写
	public void move(){
		System.out.println("猫在移动");
	}
}

多态

Java语言中的向上转型和向下转型
1.向上转型(upcasting):子—>父 (自动类型转化)
2.向下转型(downcasting):父–>子 (强制类型转换)
注:无论是向上转型还是向下转型,两个类之间必须要有继承关系

以下代码演示多态

public class Animal{
	//成员
	public void eat(){
		System.out.println("动物在吃东西");
	}
}
public class Cat extends Animal{
	//重写
	public void eat(){
		System.out.println("猫吃鱼");
	}
}
public class Dog extends Animal{
	//重写
	public void eat(){
		System.out.println("狗吃肉");
	}
}
public class Test{
	public static void main(String[] args){
		//向上转型
		//父类型引用指向子类型对象
		//程序分为两个阶段:编译简短和运行阶段
		//程序在编译阶段只知道a1是一个Animal类型
		//程序在运行的时候堆中的实际对象是Cat类型
		Animal a1=new Cat();

		//程序在编译阶段a1被编译器看作是Animal类型
		//程序在编译阶段a1引用绑定的是Animal类中的eat方法(静态绑定)
		//程序在运行的时候堆中的对象实际上是Cat类型,而Cat已经重写了eat方法
		//所以程序在运行阶段对象的绑定方法是Cat中的eat方法(动态绑定)
		a1.eat();//猫吃鱼

		//向下转型:强制类型转换
		Animal a2=new Cat();
		//执行move方法只能强制类型转换,需要加强制类型转换符
		Cat c1=(Cat)a2;
		c1.move();

		//Animal a3=new Dog();向上转型
		//强制类型转换
		Cat c2=(Cat)a3;//java.lang.ClassCastException
		//在做强制类型转换的时候程序存在风险
		//避免风险,用instanceof
		/*
		用法:
			1.instanceof运算符的运算结果是boolean类型类型
			2.(引用 instanceof 类型) -->true/false
		例如:(a instanceof Cat) 如果结果是true表示:a引用指向堆中的Java对象是Cat类型
		*/	
		Animal a3=new Dog();
		System.out.println(a3 instanceof Cat);//false
		//推荐:在做向下转型的时候要使用instanceof
		if(a3 instanceof Cat){
			Cat c2=(Cat)a3;
		}
	}
}
多态的好处

1.使用多态可以使代码之间的耦合度降低
2.项目的扩展能力增强

测试

public class Animal{
	public void eat(){
	}
}
public class Cat extends Animal{
	public void eat(){
		Sytem.out.println("猫吃鱼");
	}
}
public class Dog extends Animal{
	public void eat(){
		Sytem.out.println("狗吃肉");
public class Person{
	public void feed(Animal a){
		a.eat();
	}	
}
public class Test{
	public static void main(String[] args){
		//1.创建主人
		Person p=new Person();
		//2.创建宠物
		Dog d=new Dog();
		Cat c=new Cat();
		//3.喂
		p.feed(d);
		p.feed(c);
	}
}

super关键字

1.super不是引用类型,super中存储的不是内存地址,super指向的不是父类对象
2.super代表的是当前子类对象中的父类型特征
3.什么时候使用super?
子类和父类中都有某个数据,例如:子类和父类中都有name这个属性,如果要在子类中访问父类中的name属性,需要用到 super.
4.super可以用在什么地方?
第一:super可以用在成员方法中,不能用在静态方法中
第二:super可以用在构造方法中
语法:super(实参);
作用:通过子类的构造方法去调用父类的构造方法
语法规则:一个构造方法第一行如果没有this(…),也没有显示去调用super(…),系统默认调用super();
super(…)的调用只能放在构造方法第一行
super(…)和this(…)不能共存
super(…);调用了父类的构造方法,但是并不会创建父类对象。
在Java语言中,只要是创建Java对象,那么Object中的无参数构造方法就会执行

//父类
public class Employee{
	String name="张三";
	//成员方法
	public void work(){
		System.out.println("员工在工作!");
	}
}
//子类
public class Manager extends Employee{
	String name="李四";
	//子类将父类中的work方法重写了
	public void work(){
		System.out.println("经理在工作");
	}
	//成员方法
	public void m1(){
		super.work();
		System.out.println(this.name);//李四
		System.out.println(name);//李四
		System.out.println(super.name);//张三
	}
}

super关键字用在构造方法中

public class Account{
	//Field
	private String actno;
	private double balance;

	//Constructor
	public Account(){
		//super();//默认存在
		System.out.println("Account的无参数构造方法执行");
	}

	public Account(String actno,double balance){
		this.actno=actno;
		this.balance=balance;
	} 

	public void setActno(String actno){
		this.actno=actno;
	}

	public String getActno(){
		return actno;
	}

	public void setBalance(double balance){
		this.balance=balance;
	}

	public String getBalance(){
		return balance;
	}
}
public class DebitAccount extends Account{
	//Field
	//独特属性
	private double debit;

	//Constructor
	public DebitAccount(){
		//super();//默认存在
	}
	
	public DebitAccount(String actno,double balance,double debit){
	//通过子类的构造方法去调用父类的构造方法,作用是:
	//给当前子类对象中的父类型特征赋值
	super(actno,balance);
	thi.debit=debit;
	}

	public void setDebit(double debit){
		this.debit=debit;
	}

	public double getDebit(){
		return debit;
	}
}

final关键字

final表示不可改变的含义
1.采用final修饰的类不能被继承
2.采用final修饰的方法不能被覆盖
3.采用final修饰的变量不能被修改
4.final修饰的变量必须显示初始化
5.如果修饰的引用,那么这个引用只能指向一个对象,也就是说这个引用不能再次赋值,但被指向的对象是可以修改的
6.构造方法不能被final修饰
7.会影响Java类的初始化final定义的静态常量调用时不会执行static代码块等相关语句,这是由JVM规定的

public class Test01 {

class A{
	//final修饰的成员变量必须手动初始化
	final int i=100;
	
	//成员
	final int k;
	A(){
		k=200;
	}
}

//final修饰的成员变量一般和static连用
class MyMath{
	//常量:Java规范中要求所有的常量“大写”
	//常量:值不可再改变的变量
	public static final double PI=3.14;
}
}

/*
	深入final
	
	final修饰的是引用类型,该引用不可再重新指向其他的Java对象
	但是final修饰的引用,该引用指向的对象的属性是可以修改的
*/
public class Test02 {
	public static void main(String[] args) {
		final Customer c=new Customer("jack",15);
		
		//c是final的,无法重新赋值
		//但是c里边的属性可以重新赋值
		c.name="ad";
		c.age=25;
		
		System.out.println(c.name);
		System.out.println(c.age);
	}
}

class Customer{
	
	String name;
	int age;

	Customer(String name,int age){
		this.name=name;
		this.age=age;
	}
}

抽象类

1.如何定义抽象类
class关键字前加abstract
2.抽象类无法被实例化
3.虽然抽象类无法被实例化,但是抽象类也有抽象方法,该方法是给与类创建对象用的
4.抽象类中可以定义抽象方法(抽象类可以没有抽象方法)
抽象方法的语法:在方法的修饰符列表中添加abstract关键字,并且抽象方法应该是以“;”结束,不能带有“()”
例如:public abstract void m1();
5.抽象类中不一定有抽象方法,但抽象方法必须出现在抽象类中
6.一个非抽象的类继承抽象类,必须将抽象类中的抽象方法覆盖,实现,重写
7.避免创建父类对象
8.避免调用无意义的父类方法

public abstract class A{
	//Constructor
	A(){
		System.out.println("A...");
	}

	//抽象方法
	public abstract void m1();

	public static void main(String[] args){
		//抽象类无法创建对象
		//A a=new A();

		A a=new B();
	}
}

class B extends A{
	public void m1(){}
	B(){
		super();//父类的构造方法虽然调用了,但是并没有创建父类对象
		System.out.println("B...");
	}
}

接口(interface)

接口也是一种引用类型,可以等同看作类
1.如何定义接口,语法:
[修饰符] interface 接口名 {}
2.接口中只能出现:常量,抽象方法
3.接口其实是一个特殊的抽象类,特殊在接口是完全抽象的
4.接口中没有构造方法,无法被实例化
5.接口和接口之间可以多继承
6.一个类可以实现多个接口
7.一个非抽象的类实现接口,需要将接口中所有的方法“实现”、“重写”、“覆盖”
8.所有属性都是public static final 修饰(public static final是可以省略的)
9.所有方法都是public修饰
10.不允许有静态方法

public interface A{
	//常量必须用public static final 修饰
	public static final String SUCCESS="success";
	public static final double PI=3.14;
	//public static final是可以省略的
	byte MAX_VALUE=127;//常量

	//抽象方法(接口中所有的抽象方法都是public abstract)
	public abstract void m1();
	//public abstract是可以省略的
	void m2();
}

interface B{
	void m1();
}

interface C{
	void m2();
}

interface D{
	void m3();
}

interface E extends B,C,D{
	void m4();
}

class MyClass implements B,C{
	public void m1(){}
	public void m2(){}
	public void m3(){}
	public void m4(){}
}
接口的作用

1.可以使项目分层,所有层都可以面向接口开发,开发效率提高了
2.接口使得代码之间的耦合度降低,类似灯泡和灯口的原理,主板和内存条原理,“可插拔”

public interface CustomerService{
	//定义一个推出系统的方法
	void logout();
}
//接口实现类
public class CustomerServiceImpl implements CustomerService{
	//对接口中的抽象方法进行实现
	public void logout(){
		System.out.println("成功退出系统");
	}
}
//测试
public class Test{
	public static void main(String[] args){
		//要执行CustomerServiceImpl中的logout方法
		//以下程序面向接口去调用
		CustomerService cs=new CustomerServiceImpl();
		//调用
		cs.logout();
	}
}

Object类

toString方法
/*
	关于Object中的toString方法
		SUN在Object类中设计toString方法的目的,返回Java对象的字符串表示形式
		
		在现实的开发过程中,Object里边的toString方法已经不够用了
		因为Object的toString方法实现的结果不满意
		
		Object中的toString方法就是要被重写的
*/
public class toString {
	public static void main(String[] args) {
		//创建一个Object类型的对象
		Object o1=new Object();
		
		//调用toString方法
		String oStr=o1.toString();
		System.out.println(oStr);
		
		//创建一个Person类型的对象
		Person p1=new Person("熊大",50);
		
		//调用toString方法
		String pStr=p1.toString();
		System.out.println(pStr);
		
		Person p2=new Person("熊二",15);
		System.out.println(p2.toString());
		
		//print方法后面括号中如果是一个引用类型,会默认调用引用类型的toString方法
		System.out.println(p2);
	}
}

class Person{
	String name;
	int age;
	
	Person(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	//重写toString方法
	//根据项目的需求而定
	public String toString() {
		return "Person[name="+name+",age="+age+"]";
	}
}
equals方法
/*
 * 关于Object中的equals方法
 * Object中的equals方法:
 * public boolean equals (Object obj){
 * 		return (this==obj);
 * }
 * 
 * o1.equals(o2); o1是this,o2是obj
 * ==两边如果是引用类型,则比较内存地址,地址相同则是true,反之为false
 * Object中的equals方法比较的是两个引用的内存地址。
 * 
 * Java对象中的equals方法的设计目的:判断两个对象是否一样。
 */
public class equalsTest01 {

	public static void main(String[] args) {
		Object o1=new Object();
		Object o2=new Object();
		
		boolean b1=o1.equals(o2);
		System.out.println(b1);//false
		
		Star s1=new Star(100,"黄晓明");
		Star s2=new Star(100,"黄晓明");
		Star s3=new Star(110,"黄晓明");
		System.out.println(s1.equals(s2));//true
		System.out.println(s2.equals(s3));//false
	}
}

class Star{
	//身份证号
	int id;
	
	//姓名
	String name;
	
	//Constructor
	public Star(int id,String name) {
		this.id=id;
		this.name=name;
	}

//Object中的equals方法比较的是内存地址
//在现实的业务逻辑上,不应该比较内存地址,应该比较内容
//所以Object中的equals方法也要重写
//根据需求规定重写equals方法
//需求规定:如果身份证号一致,并且名字也一致,则代表是同一个人
//s1.equals(s2);
public boolean equals(Object obj) {
	if(this==obj) return true;
	if(obj instanceof Star) {
		Star s=(Star)obj;
		if(s.id==id && s.name.equals(name)) {
			return true;
		}
	}
	return false;
	}
}
finalize方法
/*
	关于Object中的finalize方法
		finalize方法什么时候调用?
			1.finalize方法每个Java对象都没有
			2.finalize方法不需要程序员去调用,由系统自动调用
			3.Java对象如果没有更多的引用指向它,则该Java对象成为垃圾数据
			  等待垃圾回收器的回收,垃圾回收器在回收这个Java对象之前会自动
			  调用该对象的finalize方法
			  
		finalize方法是该对象马上就要被回收了,例如:需要释放资源,则可以在该方法中释放	  
*/
public class finalize {
	public static void main(String[] args) {
		People p1=new People();
			p1=null;//没有引用在指向它,等待回收
			
			//程序员只能“建议”垃圾回收器回收垃圾
			System.gc();
	}
}

class People{
	//重写Object中的finalize方法
	public void finalize() throws Throwable{
		System.out.println(this+"马上就要被回收了");
	
	//让引用再次指向该对象,该对象不是垃圾数据,不会被垃圾回收器回收
		//Person p=this;
	}
}
hashCode方法
public class hashCodeTest01 {

	public static void main(String[] args) {
		//hashCode方法返回的是该对象的哈希码值
		//Java对象的内存地址经过哈希算法得出的int类型的数值
		hashCodeTest01 t=new hashCodeTest01();
		System.out.println(t.hashCode());
	}
}

访问控制权限

/*
 * 关于访问控制权限修饰符:修饰类,修饰方法,修饰变量
 * private 只能在本类中访问
 * default  缺省   本类,同一个包下,不同包下不行
 * protected 本类,同一个包下,不同包下不行,但是子类中可以
 * public 可以在任何位置访问
 */
public class User { //类User只能用public或者缺省方式

	//protected修饰
	protected String name;
	
	//缺省  default修饰
	int age;
}
class Test01{
	public static void main(String[] args) {
		User u=new User();
		System.out.println(u.name);
		System.out.println(u.age);
	}
}

内部类

静态内部类

1.静态内部类可以等同看作静态变量
内部类重要作用:可以访问外部类中私有的数据
2.静态内部类可以直接访问外部类的静态数据,无法直接访问成员

public class OuterClass{
	//静态变量
	private static String s1="A";
	//成员变量
	private String s2="B";
	//静态方法
	private static void m1(){
		System.out.println("static's m1 method execute!");
	}
	//成员方法
	private void m2(){
		System.out.println("m2 method execute!");
	}
	
	//静态内部类
	//可以用访问权限的修饰符来修饰
	//public protected private 缺省
	
	//静态方法
	static class InnerClass{
		System.out.println(s1);
		m1();
	}

	//成员方法
	public void m4(){
		System.out.prinln(s1);
		m1();
	}
}

	public static void main(String[] args){
		//执行m3
		OuterClass.InnerClass.m3();

		//执行m4
		InnerClass inner=new OuterClass.InnerClass();
		inner.m4();
	}
成员内部类

1.成员内部类可以等同看作成员变量
2.成员内部类中不能有静态声明
3.成员内部类可以访问外部类所有的数据

public class OuterClass {
	
	//静态变量
	private static String s1="A";
	
	//成员变量
	private String s2="B";
	
	//静态方法
	private static void m1() {
		System.out.println("static's m1 method execute!");
	}
	
	//成员方法
	private void m2() {
		System.out.println("m2 method execute!");
	}

	//成员内部类
	//可以用访问控制权限的修饰符修饰
	//public protected private 缺省
	class InnerClass{
		//静态方法
		//public static void m3(){}
		
		//成员方法
		public void m4() {
			System.out.println(s1);
			m1();
			System.out.println(s2);
			m2();
		}
	}

	//入口
	public static void main(String[] args) {
		//创建外部类对象
		OuterClass oc=new OuterClass();
		InnerClass inner=oc.new InnerClass();
		inner.m4();
	}
}

局部内部类

1.局部内部类等同于局部变量
2.局部内部类在访问局部变量的时候,局部变量必须使用final修饰

public class OuterClass {

	//方法
	public void m1() {
		//局部变量
		final int i=10;
		//局部内部类
		//局部内部类不能用访问控制权限修饰符修饰
		class InnerClass{
			//内部类不能有静态声明
			//public static void m1(){}
			
			//成员方法
			public void m2() {
				System.out.println(i);//10
			}
		}
	
	//调用m2
		InnerClass inner = new InnerClass();
		inner.m2();
	}

	//入口
	public static void main(String[] args) {
		OuterClass oc=new OuterClass();
		oc.m1();
	}
}

匿名内部类

指的是类没有名字

public class Test {
	//静态方法
	public static void t(CustomerService cs) {
		cs.logout();
	}


//入口
	public static void main(String[] args) {
		//调用t方法
		//t(new CustomerServiceImpl());
		//使用匿名内部类的方式执行t方法
		//整个这个“new CustomerService(){}”就是个匿名内部类
		t(new CustomerService(){
			public void logout() {
				System.out.println("exit");
			}
		});
		
		//匿名内部类的优点:少定义一个类
		//缺点:无法重复利用
		
		}
	}

//接口
interface CustomerService{
	//退出系统
	void logout();
}

//编写一个类实现CustomerService接口

/*
class CustomerServiceImpl implements CustomerService{
	public void logout(){
	System.out.println("系统已经安全退出!");
	}
}

*/
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值