JavaSE学习总结:面向对象编程

2023-10-27

Java面向对象编程

1.类与对象

1.1面向对象的理解

1.1.1面向对象和面向过程的区别

  • 1)都是编程思想。
  • 2)面向过程强调的是 “怎么做”,面向过程的程序,是以函数为基本单位。
  • 3)面向对象强调的是“谁来做”,面向对象是关注的是对象的个体,以类为基本单位,重点在于类的设计,某个行为,数据是在哪个类中描述更合适。

1.1.2面向对象的好处

  • 1)解决中大型的问题,使用面向对象 代码简化了;
  • 2)以人类的思维方式来思考问题,比较好理解。

1.1.3面向对象的思考步骤

  • 1、先分析里面涉及到几个类,分别是什么
  • 2、抽取每个类中的属性和方法,再加以定义
  • 3、面向过程正常调用和执行

1.2类与对象

1.2.1什么是类?

  • 对现实世界中,具有共同特性的某一类事物的抽象的描述,在Java中使用一个类来描述一类事物

1.2.2什么是对象?

  • 对象是类的一个具体的个体,是类的一个实例(instance),类是对象的设计模板,对象是类的实例。

1.2.3二者的区别

  • 类是抽象的
  • 对象是具体的,实际存在的,也称为 实体或实例

1.2.4二者的关系

  • 类是由对象总结或抽取出来的一个概念, 是对象的所属类型
  • 对象是通过类创建出来的具体的实体

1.3如何定义一个类?

  • 语法格式 【修饰符】 class 类名{
    属性列表
    构造器列表
    方法列表
    }

1.4对象的内存结构图

1.4.1栈

  • 存放方法中的基本类型变量
  • 存放方法中的引用类型 变量的引用(地址号)

1.4.2堆

  • 存放对象本身
  • 存放类的信息:类名、包名、属性的描述信息、方法的描述信息

2.类的内部成员

  • 又称为成员变量,属性的声明是在类中,方法外。

  • 声明格式:

  • 隐式声明:【修饰符】 数据类型 属性名;如何在声明类时没有显式(手动)给属性赋初始值,那么在创建对象后,这个属性有默认的初始值。byte,short,int,long 初始值为0。float,double 初始值为0.0。boolean 初始值为false。char 初始值为\u0000。引用数据类型(类、接口、数组) 初始值为null。

  • 显式初始化:【修饰符】 数据类型 属性名 = 初始值

  • 封装

  • 在属性的修饰符位置,使用private修饰。只能在本类中直接使用,在其他类中不可见。

  • 提供公共的get/set。set方法,用于为属性赋值,修改属性值。get方法,用于获取,访问某个属性的值。

2.2方法

2.1.1基本概念

  • 方法:代表一个功能的定义,具有可重用性,就可以把这样的一段代码,抽象成一个方法。
  • 一个方法完整的定义:方法的签名,修饰符 返回值类型 方法名(形参列表)抛出的异常列表。方法的实现,{
    方法的实现
    }
  • 1、只要是无返回值的方法的调用,只能是单独一个语句
  • 2、在其他类中,如果被调用的方法是static修饰,被调用的方法是无参无返回值的类名.方法名();
  • 被调用的方法是有参无返回值的,类名.方法名(实参列表);
  • 被调用的方法是无参有返回值,变量名 = 类名.方法名();
  • 被调用的方法是有参有返回值,变量名 = 类名.方法名(实参列表);
  • 如果被调用的方法是非static修饰的,同上,就是“类名.”改成“对象名.”
  • 3、要不要传实参,看被调用的方法是否声明了形参
  • 4、要不要接收返回值,看被调用的方法返回值类型是不是void,如果不是void,就可以接收,如果是void,就不能接收

2.1.2方法的分类

  • 1.无参无返回值,声明格式:
    修饰符 void 方法名(){
    方法体
    }
    调用格式:
    (1)在本类中,方法名();单独一个语句 (2)在其他类中,如果被调用的方法是static修饰,类名.方法名();如果被调用的方法是非static修饰的,对象名.方法名();Scanner input = new Scanner(System.in); //声明了Scanner对象,input.nextInt()。

-2. 有参无返回值
声明格式:
修饰符 void 方法名(形参列表){
方法体
}
其中形参列表,形参的数据类型 形参名1, 形参的数据类型 形参名2,每一个形参的声明之间使用,分割。

调用格式:
(1)在本类中,方法名(实参列表);单独一个语句。实参列表,实参直接是“常量值”,“变量名”,“表达式”;实参的个数、顺序、数据类型必须与被调用的方法的形参的个数、顺序、数据类型一一对应。
(2)在其中类中,加上类名/对象名.即可

  • 3.无参有返回值
    声明格式:
    修饰符 返回值类型 方法名(){
    方法体
    }
    调用格式:
    (1)在本类中:
    (A)经典形式,变量名 = 方法名();
    注意:这个变量的数据类型必须与被调用方法的返回值类型一致(或兼容)
    (B)作为另一个方法调用的实参,System.out.println(方法名());被调用的方法的返回值类型与另一个方法的形参的类型必须一致或者兼容。
    getVolume( getArea() , height);
    getArea()的返回值类型与getVolume()的第一个形参的类型要求一致。
    (C )作为表达式的一部分:double v = getArea(a,b) * h; //把方法的返回值 作为表达式的一部分

  • 4.有参有返回值
    声明格式:
    修饰符 返回值类型 方法名(形参列表){
    方法体
    }
    调用格式:
    (1)在本类中
    (A)经典形式 变量名 = 方法名(实参列表); 注意:这个变量的数据类型必须与被调用方法的返回值类型一致(或兼容)
    (B)作为另一个方法调用的实参
    System.out.println(方法名(实参列表));被调用的方法的返回值类型与另一个方法的形参的类型必须一致或者兼容。
    getVolume( getArea(实参列表) , height);
    getArea()的返回值类型与getVolume()的第一个形参的类型要求一致
    (C )作为表达式的一部分
    double v = getArea(a,b) * h; //把方法的返回值 作为表达式的一部分

2.1.3命令行参数

  • 给main方法传的参数
  • public static void main(String[] args)
    通过命令行传的参数,在args数组中
    如果要使用命令行的参数 args[0]…
  • java 包.类 参数1 参数2 参数3。。
    参数之间使用空格
  • eclipse,run菜单–>run configration–>选择运行哪个main方法 --》 program argument各个参数空格分隔

2.1.4可变参数

  • 可变参数的声明
    数据类型… 形参名
    声明必须在方法的形参列表的最后一个
    一个方法只能有一个可变参数
    可变参数的数据类型 可以 是任意类型

  • 可变参数的使用
    在声明它的方法中,可变参数当做数组使用,形参名就是数组.

  • 可变参数的方法调用时:
    1、可变参数的对应的位置,可以传0~n个实参.
    2、可变参数的对应的位置,可以传1个数组对象,当然这个数组对象的元素数据类型必须与可变参数的数据类型是一致.

  • 案例:

找多个整数中的最大值,至少一个

int getMax(int a , int... b){
	int max= a;
	for(int  num : b){
		if(max<num){
          max=num;	
		}
	}

	return max;
}

2.1.5方法重载

  • 特点:同一个类中,方法名相同,参数列表不同(参数个数或参数类型或参数顺序)不同,返回类型不要求。
  • 作用:允许功能相似的方法重名,使方法定义和调用都简化了。
  • 调用:正常方法调用即可,传进对应的参数,编译器自动选择 你指定类型参数的方法执行。

2.1.6方法参数传递

  • java中是按值传递的,
    基本类型做参数,值代表的是数值内容,传参相当于拷贝了一个备份到形参。形参的改变不影响实参。
    引用类型做参数, 值代表的是地址号,传参相当于传递了一个地址号(引用)到形参。形参的改变影响实参。
  • 实参将值传给形参的过程,称为参数传递,实际上就是一个赋值的过程。

2.2构造器

2.2.1基本概念

  • 又称为构造方法,创建对象必须使用构造器。

2.2.2如何声明

  • (1)无参构造
    【修饰符】 构造器方法名(){
    方法体
    }
  • (2)有参构造
    【修饰符】 构造器方法名(形参列表){
    方法体
    }

2.2.3特点

  • A:构造器方法名必须与类名相同
  • B:构造器没有返回值类型
  • C:构造器可以重载
  • D:任何类中都有构造器,如果没有显式/手动声明构造器,编译器将自动添加一个默认的无参构造器
  • E:如果显式/手动声明了任何一个构造器,编译器将不再自动添加默认的无参构造

2.2.4作用

  • (1)和new一起使用,创建对象
    new 构造方法() 调用无参构造 Random rand = new Random();
    new 构造方法(实参列表) 调用有参构造
    Scanner input = new Scanner(System.in);
  • (2)为属性赋值

2.3代码块

  • 1.静态代码块

  • 声明格式:static{
    }
    作用 为静态属性赋值

  • 2.非静态代码块

  • 声明格式:
    {
    }
    在类中,称为构造块。在方法中,称为普通代码块。

  • 作用:为非静态属性赋值,当多个构造器中重复的代码,可以提取到构造块中。

  • 3.执行的特点,静态代码块(只执行一次)–》构造块(每次创建对象) --》构造器(每次创建对象)。

public class Son extends Father {
	public Son() {
		 System.out.println("4444444444");
	}
	{
		System.out.println("555555555555");
	}
	static {
		System.out.println("66666666666");
	}
	public static void main(String[] args) {
		System.out.println("77777777777777"); 
		new Son();//3 6 7 2  1  5  4
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		new Son();//2  1  5  4
		System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		new Father();//2 1
	}
}
class Father {	
	{
		System.out.println("22222222222");
    }
	public Father() {
		 System.out.println("11111111111");
	}
	static {
		System.out.println("3333333333");
	}
}

2.4内部类

2.4.1根据声明的位置不同

  • 成员内部类
    根据是否有static修饰:1)静态成员内部类,简称静态内部类;2)非静态成员内部类,简称成员内部类。

  • 局部内部类
    根据是否有名字
    局部内部类
    匿名局部内部类,简称匿名内部类

2.4.2各种内部类的特点

  • 1.成员内部类:
    如何声明:
    【修饰符】 class 外部类{
    【修饰符】 class 内部类{
    }
    }
    如何使用:
    (1)在外部类中使用内部类:
    除了在外部类的静态成员中,不能直接使用内部类。
    在外部类的非静态成员部分,把内部类当做普通类使用。
    (2)在外部类的外面使用内部类:
    它需要外部类的对象,才能获得内部类的对象等
class Outer{
		class Inner{
		}
		
		public Inner getInner(){
			return new Inner();
		}

}


//使用 

Outer out = new Outer();
Outer.Inner in = out.getInner();

(3)在内部类中使用外部类的成员
没有限制,都能用,包括静态的,包括私有的
其他特点:
(1)外部类的权限修饰符只能是public 和缺省的,而成员内部类的权限修饰符可以4种。
(2)非静态的成员内部类中是不能包含静态成员的(静态的属性,静态方法,静态的代码块)。
(3)成员内部类有自己独立的字节码文件: 外部类名$内部类名.class,在类型描述上使用:外部类名.内部类名

  • 2.静态内部类
    如何声明:
    【修饰符】 class 外部类{
    【修饰符】static class 内部类{
    }
    }
    (1)需要在内部类中声明静态成员,那么这个内部类必须是static。
    (2)需要在外部类的静态成员中使用这个内部类,那么这个内部类也必须是static。

如何使用:
(1)在外部类中使用 没有限制
(2)在外部类的外面

class Outer{
	static class Inner{
			public void test(){
			}
	}
}

//如何调用test()
(1)test()看,它不是静态的,因此需要Inner的对象

(2)Inner在Outer里面,而Inner又是static修饰


Outer.Inner  in = new Outer.Inner();
in.test();

class Outer{


	  static class Inner{
			public static void test(){
			}
		}
}

//使用test()


(1)test(),是static修饰符,说明不需要Inner对象
(2)看Inner是static修饰,也不需要外部类的对象


Outer.Inner.test();

(3)在内部类中使用外部类的成员
在静态内部类中,不能使用外部类的非静态成员,和类的加载机制有关,static在类创建时,就要加载到内存中。
其他的成员可以直接使用,包括私有的。

其他的特点:
(1)静态的内部类,可以使用权限修饰符 4种。
(2)静态的内部类可以包含静态的成员。
(3)静态的内部类也有自己的独立的字节码文件:外部类$内部类.class。

  • 3.局部内部类
    如何声明:
    【修饰符】 class 外部类{
    【修饰符】 返回值类型 方法名(形参列表){
    class 内部类名{
    }
    }
    }
    如何使用:
    (1)在外部类中,只能在声明它的方法中,而且作用域只在声明处开始,到它所属的}结束。
    (2)在外部类的外面,不能直接使用局部内部类的类型,但是,在外部类的外面,是可以得到局部内部类的对象。
public class TestLocal {

	public static void main(String[] args) {
		MyInter m = new Out().test1();
		Object obj = new Out().test2();
	}

}
interface MyInter{
	
}
class Out{
	//使用父接口类型返回
	public MyInter test1(){
		class Inner implements MyInter{
			
		}
		return new Inner();
	}
	
	//使用父类类型返回
	public Object test2(){
		class Inner implements MyInter{
			
		}
		return new Inner();
	}
}

(3)在内部类中使用外部类的成员(成员变量,成员方法)
(4)在内部类中使用外部类的局部变量:
只能使用声明该内部类方法中,并在内部类之前声明的局部变量,而且这个局部变量要加final修饰。

其他的特点:
(1)不能使用public,protected,private,static这些成员修饰符
(2)局部内部类中,也不能包含静态成员的
(3)局部内部类也有自己的字节码文件:外部类$编号内部类.class

  • 4.匿名内部类
    如何声明 :
    【修饰符】 class 外部类{
    【修饰符】 返回值类型 方法名(形参列表){
    new 父类/父接口(){
    //内部类的成员
    }
    }
    }
    此处,父类要注意是否有无参构造器。

如何使用:
(1)使用父类的多态引用使用它对象,只能调用父类中声明过的方法。

//在main中,写一个Father的匿名内部类的对象
public class TestNiMing {
	public static void main(String[] args) {
		Father f = new Father("匿名内部类"){

			/*@Override
			public String getInfo() {
				return "内部类的示例:" + getInfo();//java.lang.StackOverflowError
			}*/
			
			@Override
			public String getInfo() {
				return "内部类的示例:" + super.getInfo();
			}
			
			public void method(){
				System.out.println("匿名内部类自己的方法");
			}
			
		};
		
		System.out.println(f.getInfo());
//		f.method();//无法访问
	}
}
class Father{
	private String info;

	public Father(String info) {
		super();
		this.info = info;
	}

	public String getInfo() {
		return info;
	}

	public void setInfo(String info) {
		this.info = info;
	}
	
}

(2)本态引用调用方法,可以调用父类的方法,也可以调用子类自己的方法。

	public static void main(String[] args) {
		//父类是Object,使用匿名内部类,声明一个方法void fun(),并调用
		new Object(){
			public void fun(){
				System.out.println("匿名内部类的方法");
			}
		}.fun();
	}

(3)作为方法的实参

import java.util.Arrays;
import java.util.Comparator;

public class TestLocal3 {

	public static void main(String[] args) {
		Dog[] dogs = new Dog[3];
		dogs[0] = new Dog(7.8);
		dogs[1] = new Dog(5.8);
		dogs[2] = new Dog(9.8);
		
		Arrays.sort(dogs, new Comparator(){

			@Override
			public int compare(Object o1, Object o2) {
				Dog d1 = (Dog) o1;
				Dog d2 = (Dog) o2;
				if(d1.getWeight() > d2.getWeight()){
					return 1;
				}else if(d1.getWeight() < d2.getWeight()){
					return -1;
				}
				return 0;
			}
			
		});
	}

}
class Dog{
	private double weight;

	public Dog(double weight) {
		super();
		this.weight = weight;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}
	
}

其他特点:
(1)没有修饰符
(2)没有构造器
(3)没有类名
(4)只有一个对象,声明匿名内部类与创建对象,同时进行
(5)也有自己独立的字节码文件:外部类名$编号.class

2.4.3为什么使用内部类

  • 1、在一个类还有一个完整的结构(有属性,方法等),需要使用内部类,而且这个内部类只为外部类服务
  • 2、内部类可以使用外部类的成员,包括私有的

3.设计模式

3.1单例设计模式

  • 某个类型在整个系统中,只有一个唯一的对象
  • 形式:
    1、懒汉式
 class Single {
        private static Single instance;

        private Single() {
        }

        public static Single getInstance() {
            if (instance == null) {
                synchronized (Single.class) {
                    instance = new Single();
                }
            }
            return instance;
        }
    }

2、饿汉式

class Single{
	public static final Single INSTANCE = new Single();
	private Single(){}
}

class Single{
	private static Single instance = new Single();
	private Single(){}
	public static Single getInstance(){
		return instance;
	}
}

要点:
(1)构造器私有化,在外面不能直接调用构造器进行创建对象。
(2)在单例类中创建这个唯一的对象,懒汉式在调用方法时,进行创建,节约内存,但是,涉及到if条件语句的判断,线程不安全,必须加上synchronized。饿汉式,直接在类加载时,创建对象,线程时安全的,同时响应速度快,一般推荐使用。

3.2模板设计模式

在父类中能确定某个功能的整体的算法结构,但是对于其中的某个步骤,在父类中无法确定,要延迟到子类中去实现,这个时候就可以通过模板设计模式。
属于抽象类的应用

计算任意一段代码或功能的运行时间

//父类:确定算法结构
abstract class  SuperClass{

	public final long getTime(){
		//1、获取开始时间
		long start = System.currentTimeMillis();
		
		//2、运行要计算时间的代码
		run();
		
		//3、获取结束时间
		long end = System.currentTimeMillis();
		
		//4、计算
		return end - start;
	}
	
	protected  abstract void run();
}

class SubClass extends SuperClass{
	protected  void run(){
		//要测试时间的代码
	}
}

3.3工厂设计模式

3.3.1目的

使得使用者与创建者分离,把创建某些接口的实现类对象交给工厂来做。

3.3.2简单工厂模式

//1、所有的要创建的对象,都是符合某个标准的
interface  Car{
	void run();
}

class BMW  implements Car{
	public void run(){
		....	
     }
}

class Benz  implements Car{
	public void run(){
		....	
     }
}

//2、设计一个工厂类,用来创建各种各样的Car的实现类的对象
class CarFactory{
	public  static Car getCar(String name){
			if("宝马".equals(name)){
				return new BMW();
			}else if("奔驰".equals(name)){
				return new Benz();
			}
			return null;
	}
}

优点:代码简洁
缺点:当增加新产品时,需要修改工厂方法,违反了“对修改关闭,对扩展开放”的原则

3.3.3工厂方法模式

//1、所有的要创建的对象,都是符合某个标准的
interface  Car{
	void run();
}

class BMW  implements Car{
	public void run(){
		....	
     }
}

class Benz  implements Car{
	public void run(){
		....	
     }
}

//2、每一种产品都自己的工厂生产
//所有的工厂就有共同的特征
interface Factory{
	Car getCar();
}
class BMWFactory implements Factory{
	public BMW getCar(){
			return new BMW();
	}
}
class BenzFactory implements Factory{
	public Benz getCar(){
			return new Benz();
	}
}

优点:如果增加新产品,只需要增加对应的工厂即可,不需要修改原来的代码。
缺点:类太多,代码复杂。

3.4代理模式

代理类来控制被代理类的方法的访问,实现AOP的基础。

3.4.1静态代理

三个角色:
主题(接口)代理类与被代理类必须都实现主题接口
代理类 必须持有被代理类对象的引用
被代理类

//主题
interface   BuyHouse{
	void trade();
}

//被代理者
class Real implements BuyHouse{
	public void trade(){
		.....	
  }
}

//代理类
class Agent implements BuyHouse{

	private  BuyHouse  target;
	
	public Agent(BuyHouse target){
		this.target = target;
	}
	
	public void trade(){
		....前置工作
		target.trade();
		...后置工作
    }
}

BuyHouse a = new Agent(new Real());
a.trade();

3.4.2动态代理

三个角色
主题(接口) 代理类与被代理类必须都实现主题接口
代理类 代理类的创建方式变了,由类加载器对象,在运行时产生
被代理类

要点
1、主题 和静态代理模式一样,就是一个接口
2、被代理类 和静态代理模式一样,实现了主题的一个实现类,负责核心业务逻辑代码。
3、处理器
用来描述,代理类要做的工作
必须实现一个InvocationHandler接口
重写一个public Object invoke(Object proxy,Method method,Object[] args)
还要持有被代理类的对象的引用

4、动态的创建代理类或代理类的对象
Proxy.newProxyInstance(被代理类的类加载器,被代理类实现的所有接口,处理器对象);
被代理类的类加载器,用来动态的在内存中生成代理类的Class对象用,即动态生成代理类,
生成代理类时,要和被代理类实现同样的接口

4.关键字的使用

4.1 this

表示当前对象
用法
this.属性 当成员变量与局部变量重名时
this.方法
this()或this(实参列表),表示调用本类的其他构造器;必须在首行;避免循环调用。

4.2 super

表示父类的引用

用法:
super.属性 当子类的属性与父类的属性重名时
super.方法 调用父类的方法实现
super()或super(实参列表) 在继承时,调用父类的构造器

4.3 static

表示静态的
修饰:
(1)属性 该属性表示所有该类的对象,共享,存储在“方法区”或“元空间”;其中一个对象对它修改,其他的对象的该属性值也会被修改。它的get/set也是static的。可以使用“显式初始化”,还可以使用“静态代码块”进行初始化。
(2)方法 该方法是类方法 可以通过“类名.”调用
(3)代码块 静态代码块,在类加载并初始化时调用,并且只会执行一次。一般用于静态属性的赋值。
(4)内部类

4.4 final

表示最终的
修饰:
(1)类 该类不能被继承
(2)属性 该属性值不能被修改,即是常量属性。该属性必须手动初始化,(1)显式初始化(2)构造块中初始化(3)在每一个构造器中初始化
(3)方法 该方法不能被重写
(4)局部变量 该局部变量的值一旦被赋值,就不能被修改,即常量

4.5 native

表示原生的
表示非Java语言实现的 ,但是使用者可以把它当做Java的方法或成员使用

4.6 instanceof

表示某个对象是否是本类或本类的子类的对象
例如:a instanceof Type 返回true a是Type的对象 或者a是Type的子类的对象

4.7 接口

  • 为什么要声明接口?
    (1)解决Java的单继承。例如:多功能的交通工具
    既具有飞机的飞行功能,
    又具有船的水上航行功能
    又具有车的路上行驶功能

(2)多个不相关的类,可能具有共同的行为特征,这样的行为特征,就可以提取成一个接口。例如:
飞机有飞的能力
小鸟有飞的能力

飞机与小鸟之间没有is-a的关系
例如:
学生对象可比较
商品对象可比较
。。。
学生与商品没有is-a的关系,可比较行为可以抽取成接口

补充了类与类之间的关系,对象与对象之间的关系,has -a 的关系,like -a的关系
因为继承只能表示is-a的关系。

  • 如何声明接口?
    【修饰符】 interface 接口名{
    }
    如果继承一个类与,实现接口同时存在,那么要先继承后实现。
    【修饰符】 class 子类 extends 父类 implements 接口名1,接口名2。。。{
    }
  • 接口的特点
    (1)使用interface声明
    (2)接口中只能有公共的抽象方法与全局静态常量
    抽象方法的 public abstract可以省略,全局静态常量的public static final可以省略
    (3)接口不能实例化,不能直接创建对象
    (4)接口用来被实现的,它的实现类如果不是抽象类,那么必须实现接口的所有的抽象方法,如果实现类是个抽象类,可以保留抽象方法
    (5)一个类可以实现多个接口(解决Java单继承的问题)
    (6)接口没有构造器
    (7)接口可以继承接口,而且可以继承多个接口
    (8)接口与实现类的对象之间是多态引用
  • 接口的应用,comparable

4.8 抽象类

  • 为什么声明抽象类?
    (1)在父类中明确子类应该包含某些方法,但是在父类中又不能给出具体的实现,父类中只能把这个方法声明为抽象方法,包含抽象方法的类必须是抽象类。
    (2)如果父类是一个抽象的概念,虽然里面没有抽象方法,但是我不希望它被创建对象,那么可以把这个类声明为抽象类。
  • 如何声明抽象类?
    【修饰符】 abstract class 抽象类的名称{
    类的成员列表
    }
  • 抽象类的特点:
    (1)使用abstract修饰
    (2)不能实例化,不能直接创建对象
    (3)抽象类可以包含抽象方法,也可以没有抽象方法
    (4)抽象类可以包含其他的成员:属性(类变量,实例变量)、方法(类方法,实例方法)、构造器(无参、有参,供子类调用)、代码块等
    (5)抽象类用来被继承的,子类继承抽象类时,如果子类不是抽象类,那么必须重写/实现父类的所有抽象方法,如果子类是抽象类,那么可以保留抽象方法
    (6)有抽象方法的类必须是抽象类
    (7)抽象类与子类的对象之间是多态引用
  • 如何声明抽象方法?
    【修饰符】 abstract 返回值类型 方法名(形参列表);没有方法体
  • 抽象类的应用
    (1)模板设计模式
abstract class  几何图形类{
	public abstract double getArea();
}

classextends 几何图形类{
	private double 半径;
    public double getArea(){
		return Math.PI * 半径 * 半径;
	}
}

class  矩形  extends 几何图形类{
	private double;
	private double;
    public double getArea(){
		return*;
	}
}

原因:
(1)从逻辑角度
几何图形类中,应该包含所有几何图形共同的特征
那么所有几何图形,就应该包含  “获取面积”的功能
(2)语法角度
通过“几何图形”类对圆对象,矩形对象等的多态引用,
应该是可以调用“获取面积”的方法,如果父类中没有声明该方法,
就无法调用,无法实现多态引用

4.9 package

  • 包的作用:
    (1)避免类的重名
    (2)限定访问权限,如果希望某个类或成员仅限于本包使用,那么该类或成员的权限修饰符是缺省的
    (3)便于管理,把功能相近的类,放在一个包中,分类管理
  • 包的声明
    package 包名;
    (1)必须在源文件的第一行
    (2)一个源文件只能有一句声明包的语句
    (3)包名的命名习惯,包名的命名规范:
    (a)域名倒置+分类的包名
    (b)全部单词都小写,每个单词之间使用.
  • 包的导入
    标准格式:import 包.类名;
    简写格式:import 包.;此处的只能代表类,不包括子包
    静态导入:import static 包.类.;此处的代表类中的静态成员(静态方法和静态的属性);意味着可以在本类中,直接使用被导入的静态成员,而不需要加“类名.”
  • 如果一个源文件声明了包
    编译的格式:javac -d 字节码文件生成的存储目录 源文件名.java
    例如:javac -d ./ 源文件名.java
    ./表示源文件的当前目录
    运行的格式 java 包.类名
  • JDK中常见的包
  1. java.lang----包含一些Java语言的核心类,如String、Math、Integer、System和Thread,Object,提供常用功能。
  2. java.net----包含执行与网络相关的操作的类和接口。
  3. java.io ----包含能提供多种输入/输出功能的类。
  4. java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
  5. java.text----包含了一些java格式化相关的类
  6. java.sql----包含了java进行JDBC数据库编程的相关类/接口
  7. java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。
  8. java.applet----包含applet运行所需的一些类。
    

4.10 new

表示创建对象,和构造器一起

4.10 extends

表示继承

5.面向对象三大特征

5.1 封装性

5.1.1目的

隐藏了实现细节,仅暴露使用的方式。安全,使用简便,隔离它的变化

5.1.2广义的封装

1、方法:把功能的实现,封装到方法中,对于使用这个方法者来说,隐藏方法的实现,暴露方法的签名,可以通过方法的签名调用即可
2、把一个事物的数据描述,行为描述封装到一个类中
3、包:如果某个类或成员的修饰符是“缺省”的,这个类或成员就仅限于本包使用
4、组件的封装:例如:网银支付,支付宝等等,提供给使用者的是“接口”
5、系统的封装:

5.1.3狭义的封装

属性的封装
1、在属性的前面加private修饰
2、公共的get/set方法

5.1.4权限修饰符

  • private
    修饰:
    (1)属性
    (2)方法
    (3)构造器 构造器的修饰符只能是private,缺省,protected,public
    (4)内部类

权限范围
仅限于本类中访问

  • 缺省
    修饰
    (1)类:外部类,内部类
    (2)属性
    (3)方法
    (4)构造器

权限范围
仅限于本包使用

  • protected
    修饰
    (1)属性
    (2)方法
    (3)构造器
    (4)内部类

权限范围
仅限于本包或其他包的子类

  • public
    修饰
    (1)类:外部类,内部类
    (2)属性
    (3)方法
    (4)构造器
    权限范围:任意位置,只不过其他包,需要导包import。

5.2 继承

5.2.1目的

  • 1、当多个类之间具有共同的特征,那么可以把这个共同的部分抽取成一个父类,这些类就可以通过继承这个父类,而达到“代码复用”,这样就不用在多个类中重复声明相同的部分
  • 2、模拟,表现现实世界中一个“is-a”的关系

5.2.2如何实现继承?

extends
语法格式 【修饰符】 class 子类名 extends 父类名{}

5.2.3继承的特点

  • 1、子类会继承父类的所有的属性和方法,但是不会继承父类的构造器。子类也会继承父类的私有的属性与方法,但是在子类中不能直接使用父类的私有成员。

  • 2、子类一定会调用父类的构造器:

  • (1)如果子类构造器中,没有写super()或super(实参列表)语句,那么默认就是调用父类“无参构造”

  • (2)子类的构造器中,也可以手动调用父类的构造器,super()或super(实参列表)

  • (3)当父类没有无参构造时,子类的构造中必须手动调用父类的有参构造super(实参列表)

  • super()或super(实参列表)它必须在子类构造器的首行

  • 3、Java中只支持单继承,但是又支持多层继承

  • (1)Java类只有一个直接父类

  • (2)Java类又支持代代相传

  • (3)Java类的根父类是java.lang.Object

5.2.4作用:

  • (1)代码复用
  • (2)表示“is-a”的关系

5.3 多态

代码更灵活

5.3.1体现

  • (1)方法的多态性:方法的重写
  • (2)对象的多态性
  • 编译时类型与运行时类型不一致,前提:
  • (1)继承+重写
  • (2)多态引用:父类的变量指向子类的对象
  • 最终表现:编译时按照父类的类型进行编译检查,运行时,执行的是子类“重写”的代码
  • 是实现多态绑定技术的前提

5.3.2数据类型的转换

  • 向上转型,多态引用,父类的变量指向了子类的对象,编译时呈现出子类的对象向上转型成父类。自动完成。
  • 向下转型,强制转换,子类类型 变量 = (子类的类型)父类的变量。
  • 要保证转型成功,这个父类的变量必须是指向该子类的对象。
  • 在转换之前加判断:if(变量 instanceof 子类的类型){
    才可以向下转型成这个子类
    }
  • 其他的都失败:
    (1)父类的变量指向父类的对象
    (2)父类的变量指向其他子类的对象
    失败报异常:java.lang.ClassCastException类型转换异常

5.3.3多态的应用

  • 1、多态参数
  • 2、多态数组
  • 3、多态属性

5.3.4面试题

  • 1、static的方法
  • static的方法不能被重写,因此也不符合多态的特征
package com.atguigu.review;
/*
 * static与多态
 * 
 * static的方法,是不能被重写
 */
public class TestStatic {
	public static void main(String[] args) {
		Father.method();//执行的是父类的方法
		Son.method();//子类的方法
		
		System.out.println("------------------");
		Father f  = new Father();//本态引用
		f.method();//可以这么调用    执行父类
		
		System.out.println("------------------");
		Son s = new Son();//本态引用
		s.method();  //执行子类
		
		System.out.println("------------------");
		Father father = new Son();//多态引用
		father.method();  //按照多态,应该执行的是子类的重写的方法   此处不符合多态的特点
	}
}
class Father{
	public static void method(){
		System.out.println("父类的静态方法");
	}
}
class Son extends Father{
	//尝试重写父类的静态方法  ,但是其实是子类自己的方法,不是重写父类的方法
	//@Override  注解的作用,是按照重写的标准来检查该方法是否符合重写的要求
	public static void method(){
		System.out.println("子类的静态方法");
	}
}
  • 2、属性
  • 属性不能被覆盖,因此也不符合多态的特征。
package com.atguigu.review;
/*
 * 属性没有重写一说,没有多态
 */
public class TestField {
	public static void main(String[] args) {
		Dad d = new Dad();
		System.out.println(d.name);//Dad
		
		Baby b = new Baby();
		System.out.println(b.name);//baby
		
		Dad dd = new Baby();
		System.out.println(dd.name);//Dad
	}
}
class Dad{
	String name = "Dad";
}
class Baby extends Dad{
	String name = "baby";
}
  • 3、可变参数
package com.atguigu.review;

public class TestSub {

	public static void main(String[] args) {
 		Base base=new Sub();//多态引用
  		base.add(1,2,3);//2,3已经按照数组去编译
	}
}
class Base {
	public void add (int a,  int... arr ){
		System.out.println("base");
	}
}
class Sub extends Base{
	
	public void add(int a, int[] arr  ){
		System.out.println("sub_1");
	}
	
	public void add(int a , int b, int c ){
		System.out.println("sub_2");
	}
}

6 总结

面向对象编程是java中最基础的部分,后面的框架Hadoop、Spark等都是对这章内容的应用。一开始还是觉得很抽象,当逐步深入的去了解框架后,再回过来看面向对象,就应了那句话“java中,万事万物皆对象”。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaSE学习总结:面向对象编程 的相关文章

随机推荐

  • 【论文笔记15】以太坊智能合约去中心化的链上数据访问

    原文作者 Mohd Sameen Chishti Farhan Sufyan and Amit Banerjee Member IEEE 原文标题 Decentralized On Chain Data Access via Smart C
  • Oracle建表报错:ORA-00955:名称已由现有对象使用

    现象描述 在Oracle数据库中已经创建了 staff表 现在因为业务需求 创建与staff表结构相同的测试表 test staff test staff表创建语句如下所示 create table test staff STAFF ID
  • Javeweb项目微服务集群部署

    基于Springcloud的javaweb项目部署集群环境 采用jdk运行 jar包 consul 进行注册服务监控健康 实现并发量大的时候可以快速响应的高并发效果 操作过程如下 1 安装nfs服务 2 安装相应中间件服务 3 安装数据库以
  • MySQL - 唯一索引

    唯一索引 所谓唯一索引 就是在创建索引时 限制索引的字段值必须是唯一的 通过该类型的索引可以比普通索引更快速地查询某条记录 1 创建表时定义索引 CREATE TABLE tablename propname1 type1 propname
  • 利用用adb查看短信、通讯录、拨号的应用数据

    利用用adb查看短信 通讯录 拨号的应用数据 1 进入root界面 adb shell su 2 查看你想要查看的应用手机目录下应用界面的包名 adb shell dumpsys activity findstr mFocusedActiv
  • 第 0004 题: 任一个英文的纯文本文件,统计其中的单词出现的个数

    import os file open wz txt mode r dict for line in file h line line split for key in h line if key 1 gt a and key 1 lt z
  • Centos-启动network报错RTNETLINK answers: File exists解决方法

    背景 今天在Vcenter上 用模板克隆了一个虚拟机 启动之后 网卡启动不了 报错如下 RTNETLINK answers File exists 说明 环境 Centos6 6 X64 网卡两个 原因 由于用模板克隆虚拟机 所以网卡的配置
  • ts类型体操Concat

    533 Concat by Andrey Krasovsky bre30kra69cs easy array Question Implement the JavaScript Array concat function in the ty
  • 总结的一些MySQL索引相关的知识点

    博客迁移 http cui zhbor com article 14 html MySQL索引 有很多很多的东西需要去学习 我会写一些自己的总结 这些总结主要是平时运用在实际项目中的 有很多的经验往往设计表的人很清楚 但是总是有 这个东西就
  • 【实例分割】3、Mask Scoring R-CNN

    文章目录 摘要 1 引言 2 相关工作 2 1 实例分割 2 2 检测得分校正 3 方法 3 1 动机 3 2 Mask scoring in Mask R CNN 4 实验 4 1 实验细节 4 2 定量结果分析 4 3 消融学习 4 4
  • 时序逻辑和组合逻辑

    一 组合逻辑与时序逻辑的对比 1 组合逻辑的输出状态与输入直接相关 时序逻辑还必须在时钟上升沿触发后输出新值 2 组合逻辑容易出现竞争 冒险现象 时序逻辑一般不会 3 组合逻辑的时序较难保证 时序逻辑更容易达到时序收敛 时序逻辑可控 4 组
  • IP代理安全吗?如何防止IP被限制访问?

    你是否遇到过可以正常上网 但访问某个网站却被禁止 注册某个网站账号 却被封号 那都是因为IP出现问题 您的IP地址透露很多关于您的信息 包括您的位置和互联网活动 在本文中 我们将一起了解IP地址 网站如何利用它来跟踪您 以及与IP代理如何帮
  • 求助:stm32+proteus+adc采集电压仿真显示为零

    求助一下大佬 因为板子上的oled不是ssd1306驱动的所以现在只能学习跑仿真 在学adc采集电压的实验 OLED显示没问题 现在的问题是采集不到电压 显示总是0 麻烦好心人帮我看看是哪里出了问题 软件用的keil mdk5 24 pro
  • Game【HDU-6873】【Splay】

    2020 Multi University Training Contest 9 G题 题意 有N个有各自高度的位置 按1 N从左到右排列 现在我们有两种操作 x y将第x列 第y行的方块 包括它上面的方块从右往左的移动过去 同时推动前面的
  • 【导入导出测试用例编写】

    导入导出测试用例编写 一 导出模板测试用例 二 导出数据测试用例 三 导入数据测试用例 一 导出模板测试用例 1 检查模板是否可以正常下载正常打开 2 检查模板表头格式展示是否正确 与系统列表中的字段是否一致 3 检查必填项 字段长度 字段
  • 接口性能 指标

    接口测试响应时间 通用得接口响应使时间分布情况 100ms为优良 500ms为及格 1000ms以上为不可忍受 金融接口响应时间得分布情况 100ms为优良 200ms为及格 300ms以上为不可忍受
  • 动态链接库(一)--动态链接库简介

    写在前面 自从微软推出的第一个版本的Windows操作系统以来 动态链接库 DLL 一直就是Windows操作系统的基础 动态链接库通常不能直接运行 也不能接收消息 它们一直是独立的文件 其中包含能被可执行程序或其他DLL文件调用来完成某项
  • 【解决ElementUI 和Antd的对话弹窗样式冲突问题】

    项目中使用了Antd 和element UI两种UI库 Antd是全局样式 element ui则是按需引入 在使用element ui的页面处点击退出 弹出的对话框就会样式失效 首先在随便一个地方点击退出登录看一下正常效果 再打开F12查
  • Unity3D中的ref、out、Params三种参数的使用

    目录 ref out Params ref 作用 将一个变量传入一个函数中进行 处理 处理 完成后 再将 处理 后的值带出函数 语法 使用时形参和实参都要添加ref关键字 using System Collections using Sys
  • JavaSE学习总结:面向对象编程

    Java面向对象编程 1 类与对象 1 1面向对象的理解 1 1 1面向对象和面向过程的区别 1 1 2面向对象的好处 1 1 3面向对象的思考步骤 1 2类与对象 1 2 1什么是类 1 2 2什么是对象 1 2 3二者的区别 1 2 4