Java 面向对象知识

面向对象的特性

一、封装

  • 原则:将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。
  • 封装的操作步骤
    1、使用 private 关键字来修饰成员变量。
    2、对需要访问的成员变量,提供对应的一对get 、set方法。
  • private的含义
    1、private是一个权限修饰符,代表最小权限。
    2、可以修饰成员变量和成员方法。
    3、被private修饰后的成员变量和成员方法,只在本类中才能访问。
public class Student { 
		private String name; 
		private int age; 

		// 无参数构造方法 
		public Student() {}
		// 有参数构造方法 
		public Student(String name,int age) { 
				this.name = name;
				 this.age = age; 
		}
		public void setName(String name) { 
				//name = name; 
				this.name = name;
		 }
		 public String getName() { 
				 return name; 
		 }
}

this代表所在类的当前对象的引用(地址值),即对象自己的引用。
使用 this 修饰方法中的变量,解决成员变量被隐藏的问题


当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。
所有的类都有构造方法,因为Java自动提供了一个无参数构造方法,
一旦自己定义了构造方法,默认无参数构造方法就会失效。
即使还需要无参构造方法也要自己定义。

JavaBean(了解)

JavaBean 是 Java语言编写类的一种标准规范。
符合 JavaBean 的类,要求类必须是具体的和公共的,并且具有无参数的构造方法,提供用来操作成员变量的 set 和 get 方法。

二、继承

  • 定义:
    类和类之间关系的一种表示,继承是面向对象最显著的一个特性
    继承实际上就是属性和方法的重用,不让我们写多余的代码
    子类除了继承父类的属性和方法外,还可以写自己特有的属性和方法

  • 继承的作用:
    子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。
    子类可以直接访问父类中的非私有的属性和行为,但无法继承private 修饰的方法和属性。

    • 所有类都是Object的子类
    • 父类:被继承的类,也可以成为超类或基类
    • 子类:继承的类,也可以称为派生类
    • 继承需要合乎情理,不能乱继承
  • 继承的格式:

class B extends A{ }		//B继承A,A是B的父类,B是A的子类
  • 继承说明:一个类最多只有一个父类,但一个类可以有多个子类(如Object类)

  • 既然Object是所有类的父类,所以Object类中的属性和方法是可以直接用的

继承后的特点

a、成员变量

  1. 父类子类成员变量不重名———访问没有影响
  2. 父类子类成员变量重名
    在子类中需要访问父类中非私有成员变量时,需要使用 super 关键字,修饰父类成员变量,类似于 this 。
super.父类成员变量名

class Zi extends Fu { 
	// Zi中的成员变量 
	int num = 6; 
	public void show() { 
		//访问父类中的num 
		System.out.println("Fu num=" + super.num); 
		//访问子类中的num 
		System.out.println("Zi num=" + this.num); 
		} 
	}

Fu 类中的成员变量是非私有的,子类中可以直接访问
若Fu 类中的成员变量私有了,子类是不能直接访问的。
通常编码时,我们遵循封装的原则,使用private修饰成员变量,
访问父类的私有成员变量
可以在父类中提供公共的getXxx方法和setXxx方法。

b、成员方法

  1. 成员方法不重名———访问没有影响

对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法

  1. 成员方法重名———重写(Override)

方法重写 :子类中出现与父类一模一样的方法时
(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。


重写应用:
子类可以根据需要,定义特定于自己的行为。
既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从而进行扩展增强。
比如新的手机增加来电显示头像的功能,代码如下:

class Phone { 
	public void sendMessage(){ 
		System.out.println("发短信"); 
	}
	public void call(){ 
		System.out.println("打电话"); 
	}
	public void showNum(){ 
		System.out.println("来电显示号码");
	}
 }

class NewPhone extends Phone { 
	//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能 
	public void showNum(){ 
	//调用父类已经存在的功能使用super
	super.showNum(); 
	//增加自己特有显示姓名和图片功能 
	System.out.println("显示来电姓名"); 
	System.out.println("显示头像"); 
	} 
}

这里重写时,用到super.父类成员方法,表示调用父类的成员方法。

super :代表父类的存储空间标识(可以理解为父亲的引用)。
this :代表当前对象的引用(谁调用就代表谁)。

c、构造方法

  1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
  2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。

d、父类空间优先于子类对象产生(子类对象中包含了其对应的父类空间)

在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。

三、抽象类

概述

  1. 有时候,我们可能想要构造一个很抽象的父类对象,它可能仅仅代表一个分类或抽象概念,它的实例没有任何意义,因此不希望它能被实例化。
  2. 通过在class关键字前增加abstract修饰符,就可以将一个类定义成抽象类。抽象类不能被实例化。
  3. Java语法规定,包含抽象方法的类就是抽象类,但抽象类不一定含抽象方法。

抽象方法

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。
那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法
使用 abstract 关键字修饰方法,该方法就成了抽象方法。

定义格式: 
    修饰符 abstract 返回值类型 方法名 (参数列表);
代码举例: 
    public abstract void run();

抽象类

public abstract class Animal { 
	public abstract void run(); 
}

抽象方法的使用

继承抽象类的子类必须重写父类所有的抽象方法。
否则,该子类也必须声明为抽象类。
最终,必须有子类实现该父类所有的抽象方法,
否则,从最初的父类到最终的子类都不能创建对象,失去意义。

抽象类不能创建对象,只能创建其非抽象子类的对象。
抽象类中可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
抽象类中不止含有抽象方法。还可以含有成员变量、成员方法等。

四、接口

  1. 接口的内部主要就是封装了方法,包含抽象方法,默认方法和静态方法(JDK 8),私有方法 (JDK 9)。
  2. 接口的定义,使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。(引用数据类型:数组,类,接口)
  3. 接口的使用,它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。
public interface 接口名称 { 
	// 抽象方法 
	// 默认方法 
	// 静态方法 
	// 私有方法 
}

抽象方法:使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。

public abstract void method();

默认方法:使用 default 修饰,不可省略,供子类调用或者子类重写。
静态方法:使用 static 修饰,供接口直接调用。

public default void method() { // 执行语句 }
public static void method2() { // 执行语句 }

私有方法:使用 private 修饰,供接口中的默认方法或者静态方法调用。

接口实现

  1. 必须重写接口中所有抽象方法。
  2. 继承了接口的默认方法,即可以直接调用,也可以重写。
class 类名 implements 接口名 { 
	// 重写接口中抽象方法【必须】 
	// 重写接口中默认方法【可选】 
}

接口的多实现

  1. 一个类只能继承一个父类
  2. 一个类可以实现多个接口
  3. 一个接口可以继承多个接口
  4. 以上可以同时存在

接口作为成员变量:(赋给它该接口的一个子类对象)

public interface FaShuSkill { 
	public abstract void faShuAttack();
 }

public class Role {
	FaShuSkill fs;
	public void setFaShuSkill(FaShuSkill fs) { 
		this.fs = fs;
	 }
//接口作为成员变量时,对它进行赋值的操作,实际上,是赋给它该接口的一个子类对象。
	 ...

接口作为返回类型和方法参数:(其实都是它的子类对象)

public List<Integer> get(List<Integer> list) {
	ArrayList<Integer> evenList = new ArrayList<>();
	return evenList;
	// List 接口作为参数或者返回值类型时,可以将 ArrayList的对象进行传递或返回
}

如果抽象方法有重名的,只需要重写一次。
如果默认方法有重名的,必须重写一次。
存在同名的静态方法并不会冲突,原因是只能通过各自接口名访问静态方法。


接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
接口中,没有构造方法,不能创建对象。
接口中,没有静态代码块。

抽象类与接口的区别:

接口中变量都是静态(static)的常量(final)(全局常量)
抽象类中可以有实例变量。
方法方面各有侧重。。。

继承与实现接口的区别:

继承与实现接口的四大区别

使用继承,可以减少代码量,常用方法可以不必定义,而是直接继承父类定义好了的方法,提高编程效率。体现了软件的三特性之一的可复用性。
使用接口,只定义方法,没有具体的方法体,实现该接口的类可以对接口中的方法灵活的根据实际情况定义,很好的是程序具有灵活、复用的特性。


java允许一个接口继承多个父接口,也允许一个类实现多个接口,而这样的多继承有缺点吗?
答案是没有,这是由接口的抽象性决定的。
参考文章(时代久远,jdk1.8后接口中不止抽象方法,可含有方法体)

五、多态

多态存在的必要条件:

  • 必须要有继承或者实现 (Person 由Student,Teacher继承)
  • 要有重写 /////Person(eat()) Student(eat(重写))
  • 父类引用指向子类对象Person per=new Student();
  • 格式:父类类型 变量名 = new 子类对象;

多态的使用:
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;
如果有,执行的是子类重写后方法。(父类执行)

多态的好处:
父类类型作为方法形式参数,传递子类对象给方法。(根据需求传递不同的子类对象)

引用类型转换:

  • 多态的转型分为向上转型与向下转型两种:
  • 向上转型:默认的,当父类引用指向一个子类对象时,便是向上转型。
  • 向下转型:强制转换,向上转型的子类对象,将父类引用转为子类引用

向下转型:子类类型 变量名 = (子类类型) 父类变量名;
使用条件:父类变量想要使用子类的特有的方法时。

六、final 关键字

用于修饰不可改变内容

  • 类:被修饰的类,不能被继承。
  • 方法:被修饰的方法,不能被重写。
  • 变量:被修饰的变量,不能被重新赋值。
修饰变量:

局部变量——>基本类型

  • 只能赋值一次,不能再更改。

局部变量——>引用类型

  • 只能指向一个对象,地址不能再更改

成员变量:只能赋值一次(直接赋值 / 构造器赋值)

七、匿名内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。

匿名内部类是内部类的简化写法。

前提:匿名内部类必须继承一个父类或者实现一个父接口

public class InnerDemo { 
	public static void main(String[] args) { 
		/*1.等号右边:是匿名内部类,定义并创建该接口的子类对象 
		2.等号左边:是多态赋值,接口类型引用指向子类对象 */ 
		FlyAble f = new FlyAble(){ 
			public void fly() { 
				System.out.println("我飞了~~~"); 
			} 
		};
		//用法一、调用 fly方法,执行重写后的方法
		f.fly(); 
		//用法二、将f传递给showFly方法中 
		showFly(f);

	} 
}

异常类

  • Exception类是所有异常类的根类
  • 处理格式:
try{
		//可能发生异常的程序
}catch(Exception e){
		//对异常进行处理
}

//补充:可以使用多个catch分别针对不同的异常进行捕获

在myeclipse代码块右击选择source中的format可以整理代码
Alt +/ :智能补充
Ctrl +1:智能提示解决报错的方法
CTRL+shift+O:导入所有需要的包
ALT+shift+S:生成对话框可直接生成private属性下的Get和Set方法;也可以生成有参和无参的构造函数。

集合框架

  • 格式:在这里插入图片描述
  • 介绍一个list类,可以用来存放对象实例。
package com.java.collection;
import java.util.ArrayList;
import java.util.List;

public class Test {

	public static void main(String[] args) {
	
				List<Person> list=new ArrayList();		//限定list中只能存放Person对象
				
				Person p1=new Person();
				p1.setName("zhangsan");
				p1.setAge(21);
				Person p2=new Person("lisi",20);
				
				list.add(p1);
				list.add(p2);
									//for循环遍历取出list中的对象
				for(Person p:list){
					System.out.println(p.getName()+"::"+p.getAge());
				}		
	}
}

IO流

  • 定义:
    IO流 :Input/Output | 输入/输出
    输入————读取
    输出————写出去
  • 流的分类:
    a.字符流 b.字节流

字符流读取文本文档中的内容:
FileReader类
FileReader fr = new FileReader("文件名"); //这个类已经关联到一个文件上
//
fr.read(c)=-1表示已经读完整个文件
//
while(fr.read(c)!=-1){ System.out.println(c); }//利用循环,在一个小的空间迭代覆盖读出一个大的文件,可节省空间

			//报错:找不到指定文件
			try {
				FileReader fr=new FileReader("hello.txt");
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			//需要加上完整路径:E:\\jdk\\hello.txt(\\有一个是转义符)
			char[] c = new char[20];	
			int num = fr.read(c); 	//是将我们的内容读到一个字符数组中 num就代表读到的长度
			
			System.out.println(fr.read());
			// 由于所有内容都读进了数组中,所以fr.read()读到的是-1,文件的末尾标志

			String str = new String(c, 0, num); 	// 定义String用到的截取方法
			System.out.println(str);
			char[] c= new char [20];
			fr.read(c);
			
			while(fr.read(c)!=-1){
				System.out.println(c);
			}
			/*fr.read(c)每次读,下次就会记住读到的位置,如果到了文件末尾则返回值为-1,
			不然返回值就是这次读到的长度*/

利用字符流去写一段内容:
FileWriter类
FileWriter fw=new FileWriter("E:\\123.txt"); //可以看到这个文件已经被创建出来
//
FileWriter fw=new FileWriter("E:\\123.txt",true); //后面加上true就表示是续写, 不会覆盖原来内容

try {
			FileWriter fw=new FileWriter("E:\\123.txt",true);	//可以看到这个文件已经被创建出来
			//接下来我们的任务就是通过这个对象,调用这个对象的方法,实现写的操作
			
			fw.write("中国加油!");
			
			
//			fw.flush();		//刷新一下缓冲区,告诉它,将其写到文件中去
			fw.close();		//将该流关闭,一关闭就写完了(读写操作都应该养成关闭流的好习惯)
			
		} catch (Exception e) {
			e.printStackTrace();
		}

File类是一个对文件进行操作的类,具体使用可百度或者api

发布了33 篇原创文章 · 获赞 2 · 访问量 978

猜你喜欢

转载自blog.csdn.net/Rhin0cer0s/article/details/88421973