JAVA SE基础(二)——面向对象编程(类、static、final)

目录

面向对象(OOP)编程

面向对象的三大特征 —— 封装、继承、多态

类与类之间的关系

类的概述

类的内存空间

类的属性(成员变量vs局部变量)

类的方法(提供功能的实现)

包装类(Wrapper,封装类)

补充

匿名类对象:创建类的对象是匿名的——即没有实例对象的名字(当只需要一次调用类的对象)

可变个数的形参:

关键字——this:

JavaBean —— 一种Java语言写成的可重用组件

UML类图

this和super的区别:

JUnit

关键字

static  ——  静态,修饰属性、方法、代码块(初始化块)、内部类

关键字  final  ——  声明类、属性、方法(最终的)

【注】


 

面向对象(OOP)编程

面向对象和面向过程都是一种思想,面向对象强调的是将功能封装进“对象”,即具备了功能的对象;面向过程强调的是功能行为。

  • 类是对一类事物描述,是抽象的、概念上的定义

  • 对象是实际存在的该类事物的每个个体,也称为实例

  • 一切皆对象

  • 类成员 --> 类的实例化(创建类的对象)

①属性:类中的成员变量

②行为:类中的成员方法

 

面向对象的三大特征 —— 封装、继承、多态

  • 封装(Encapsulation——使用者如果对类内部定义的属性直接操作会导致数据的错误、混乱或安全性问题

①创建类对象之后,若直接使用“对象.属性”进行属性赋值或调用的话,可能会出现不满足实际情况的意外,考虑不直接作用属性,使用“对象.方法”来控制对属性的控制访问

②将类的属性私有化,提供公共的方法来调用控制属性(setter()&getter())

权限修饰符:public、private、default(缺省)、protect(也可看作Java作用域的范围)

修饰符类内部同一个包子类任何地方
privateyes   
default(缺省)yesyes  
protectedyesyesyes 
publicyesyesyesyes

【注】

     Java  权限修饰符public、protected、private置于类的成员定义之前,用来限定对象对该类成员的访问权限。

      对于class的权限修饰符只可以用public和default(缺省)。public类可以在任意地方被访问; default类只可以被同一包内部的类访问。

      可修饰属性、方法。

      权限大小:public    protected    default    private

      修饰类的权限:public、default(缺省)

 

  • 继承(Inheritance)——继承父类,自我进化(子类对父类的扩展

①通过<class A extends B>来实现类的继承——(子类:A;父类、基类、超类(superclas):B)

②子类继承父类后,父类中的声明的属性、方法,子类就可以获得(当父类中私有的属性或方法时,子类可以获取到,但是由于封装性,不能显式调用属性),子类可以设计自己独有的属性、方法

java类的继承只支持单继承(“多继承”可通过接口实现)

④子类、父类只是相对的概念

⑤关键字 super——使用super来调用父类中的指定操作

·super可用来访问父类中定义的属性

·super可用于调用父类中定义的成员方法

·super可用于在子类构造方法中调用父类的构造器(super()声明在首行,this()和super()只能出现一个,若均未出现则默认调用super())

【注】

       ·尤其当子父类出现同名成员时,可以用super进行区分

      ·super的追溯不仅限于直接父类

      ·super和this的用法相似,this代表本类对象的引用,super代表父类的内存空间的标识

⑥子类对象实例化的全过程:

子类(当前类)的构造器  ( 子类的父类的构造器 ( 父类的父类的构造器 (… (Object类构造器))))——自内向外

  • 多态(Polymorphism)———一个事物的多种表型形态,可以直接应用在抽象类和接口上
  1. 方法的重载(overload)和重写(overwrite)

  2. 若编译时类型和运行时类型不一致,就会出现多态。(Java引用变量有两个类型:编译时类型运行时类型;编译时类型由声明该变量时使用的类型决定;运行时类型由实际赋给该变量的对象决定

  3. 子类对象的多态性:父类的引用指向子类对象

//类之间的多态性
/**
*类的继承
*子类对父类的重写
*/
class Person{
    public void work(){
        System.out.println("人需要工作");
    }
}

class Man extends Person{
    public void work(){
        System.out.println("男人需要工作");
    }
}

//父类的引用指向子类对象
Persosn person = new Man();
//实际执行的是子类重写父类的方法
person.work();//男人需要工作

//“强制转换”
Man man = (Man) person;



//编译时、运行时的状态

/**
***编译时:“看左边”,将此引用变量理解为父类的类型
***运行时,“看右边”,关注于真正对象的实体————子类的对象。执行的方法即子类的重写方法
*/

【补】Person类  instanceof Man类:判断Person是否是Mande 的实例。返回true/false。true——Person一定是Man的父类(Person)的实例

4.类的属性——无多态性(对于同名属性,调用时根据类的实例化对象调用)

class Person{
    public String name = "person";
}

class Man extends Person{
    public String name = "man";
}

Person person = new Man();

System.out.println(person.name);//person

Man man = (Man) person;

System.out.println(man.name);//man

5.Object类   ——  [ java.lang.Object,所有类的根父类 ]

      ·equals()  —— 比较引用类型变量的地址值是否相等

String s1 = "string":
String s2 = "string";
String s3 = new String("string");

s1==s2;//true

s1.equals(s2);//true

s1==s3;//false

s1.equals(s3);//true

      `toString() —— 返回值为String , 返回类名和其引用地址

            ①在进行String与其他类型数据的连接操作时,自动调用toString()方法

            ②可以根据需要在用户自定义类型中重写toString()方法

            ③基本数据类型转换为String类型时,调用了对应包装类的toString()方法

/**toString()方法
*
*/

//java.lang.Object类的toString()方法:
public String toString(){
    return getClass().getName() + “@” + Integer.toHexString(hashCode());
}

/**
1、当打印一个对象的引用时,默认调用该对象的toString()方法
2、当打印的对象所在的类没有重写Object中的toStrig()方法时,那么调用的就是Object中定义的toString()方法,返回此对象所在的类及对应的堆空间对象实体的首地址值。
3、当打印的对象所在的类重写了toString()方法时,调用的就是重写之后的toString()方法
4、相应的包装类已经重写Object类中的toString()方法
*/

 

类与类之间的关系

  • 关联关系——在类中定义且使用其他类
  • 继承关系——子类中有父类所有的方法和属性,可重写父类的方法,子类对父类进行“扩展”
  • 聚合关系——多个类是一个类的一部分

①聚集——类中的内类可以在其他类中

②组合——类中的内类不可未其他的内类

类的概述

  • 设计类,并设计类的成员(成员变量&成员方法)
  • 通过类来创建类的对象(也称作类的实例化)
        class class_name {
		private int id;
		private String name;
		public class_name() {

		}
		public class_name(int id, String name) {
			super();
			this.id = id;
			this.name = name;
		}
		public int getId() {
			return id;
		}
		public void setId(int id) {
			this.id = id;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		

	}
//实例化
class_name name1=new class_name();

//类的访问机制
/**
*在一个类中:类中的方法可直接访问类中的成员变量。(static方法不得访问非static)
*在不同类中:先创建要访问的类的对象,再用对象访问类中定义的成员
*/
  • 通过“对象.属性”、“对象.方法”来调用,完成相应的功能

类的内存空间

创建多个对象,各自拥有自己的类的属性。一个对象属性的修改,不会修改其他的对象。

  • 栈(Stack):局部变量、对象的引用名、数组的引用
  • 堆(Heap):new出来的“实体”(含成员变量)
  • 方法区:包含字符串常量
  • 静态区:声明为static的变量

类的属性(成员变量vs局部变量)

  • 遵循变量声明的格式:[数据类型] [变量名] = [初始化值];
  • 都有作用域
  • 声明的位置不同成员变量:声明在类内,方法之外;局部变量:声明在方法内,方法的形参部分,代码块内
  • 成员变量的修饰符:private、public、protected、缺省 ; 局部变量没有修饰符,与所在方法的修饰符相同
  • 初始化值:一定有初始化值;成员变量:如果在声明的时候不显式赋值,不同的数据类型有不同的默认初始化值;局部变量:一定显式赋值(无初始化值)
  • 局部变量和成员变量在内存中的存放位置不同:成员变量:堆空间中;局部变量:栈空间中

类的方法(提供功能的实现)

  • 格式:[权限修饰符]  [返回值类型] [方法名](形参,……){ 功能实现代码块 }
  • 方法内可调用类内的方法,但不可方法内定义新方法
  • 方法的重载(Overload):同一个类中,方法名相同,方法的参数列表不同(参数的个数,参数的类型,不同的参数顺序)—— 方法的重载与返回值类型没有关系!
  • 方法的参数传递:

①形参:方法声明时的参数;实参:方法调用时实际传给形参的参数值。

/**Java的实参值如何传入方法?
*Java的方法参数传递方式只有一种:值传递(即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响)

**java种的参数传递机制:值传递
i) 形参是基本数据类型:将实参的值传递给形参的基本数据类型的变量
ii)形参是引用数据类型:将实参的引用类型变量的值(对应堆空间的对象实体的首地址值)传递给形参的引用类型变量
*/
  • 构造器(constructor   构造方法————非传统意义的Java方法(此方法非彼方法)【创建类】
  1. 特征:①具有与类相同的名称;②不声明返回值类型。(与声明为void不同);③不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值
  2. 作用:创建对象;给对象初始化
  3. 类对象属性赋值的先后顺序:①属性的默认初始化;②显式初始化;③通过构造器给属性初始化;④通过对象.setXX()的方式给属性赋值
class person{
    private String name;
    private String sex;
    //创建对象(空参构造器,系统默认提供,若不显式实现)
    //public person(){
    //}
    //创建对象,且给对象初始化(若未定义空参构造器,覆盖空参构造器)
    public persion(String name,String sex){
        //super();
        this.name=name;
        this.sex=sex;
    }

}

/**
*构造器格式:[权限修饰符] [类名] (形参){//代码块}
*多个构造器之间即重载
*/
  • 方法的重写(override、overwrite)——子类继承父类,若父类的方法对子类不适用,子类对其重写使其适用于子类

【规则】:①要求子类方法的“返回值类型、方法名、(参数列表)”与父类方法一致; ②子类的方法的修饰符不能小于父类方法的修饰符; ③若父类方法抛异常,那么子类方法抛出的异常类型不能大于父类; ④子父类的方法必须同为static或非static

包装类(Wrapper,封装类)

基本数据类型包装类
booleanBoolean
byteByte
shortShort
intInteger
longLong
charCharacter
floatFloat
doubleDouble
  • 基本数据类型 -> 包装类:调用包装类的构造器

  • 包装类 -> 基本数据类型:包装类Xxx的XxxValue()方法(jdk1.5以后实现自动的装箱、拆箱)

Inerger i = 12;//自动装箱
int i1 = i;//自动拆箱
  • 基本数据类型、包装类 -> String类:调用String类的重载的valueOf(Xxx x)方法

  • String -> 基本数据类型、包装类(Xxx) :Xxx.parseXxxt(String  s)方法

补充

  • 匿名类对象:创建类的对象是匿名的——即没有实例对象的名字(当只需要一次调用类的对象)

new class_name().getName();
//new class_name()即匿名类
//创建的匿名类的对象只能调用一次
  • 可变个数的形参:

①格式:[ 数据类型 ] ... [形参名]

②可变个数形参的方法与同名方法构成重载

③可变个数的形参在调用时,个数从0开始,可到无穷多个

④使用可变多个形参的方法与数组形参的使用是一致的

⑤方法中有可变个数形参时,一定要声明在形参列表的最后

⑥在一个方法中,最多声明一个可变个数的形参

//采用数组形参来定义方法
public static void Method(int num,String[] array){}

//以可变个数形参来定义方法
public static void Method1(int num,String...array){}

/**
*可变参数:方法参数部分指定类型的参数个数是可变个数
*声明方式:方法名(参数的类型名...参数名)
*可变参数方法的使用与方法参数部分使用数组是一致的
*方法的参数部分有可变形参,需要放在形参声明的最后
*/
  • 关键字——this:

①在方法内部使用(即此方法所属对象的引用);

②在构造器内部使用,表示该构造器正在初始化的对象

③this表示当前对象,可以调用类的属性、方法和构造器(i.当形参与成员变量重名时,若在方法内部需要使用成员变量,必须添加this来表明该变量时类成员;ii.在任意方法中,若使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性。)

④当在方法内需要用到调用该方法的对象时,就用this

⑤可以在构造器种通过<this(形参)>显式调用本类中其他重载的指定的构造器

  • JavaBean —— 一种Java语言写成的可重用组件

类是公共的;有一个午餐的公共的构造器;有属性,且有对应的get、set方法。

用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变。

  • UML类图

  • package:声明源文件所在的包,程序的第一行;每“.”一次,表示一层文件目录;包名要小写;
  • import: 显式导入指定包下的类或接口;写在包的声明或源文件之间;如果需要引入多个类或接口,那么并列写出;如果导入的类在java.lang包下,无需显式声明(默认导入);java.util.*(导入java.util包下所有的类);处理同名类(不同包下的类);import static 表示导入指定类的static的属性和方法;导入java.lang.*只能导入lang包下的所有类或接口,不能导入lang的子包下的类或接口

【常用java包】

  1. java.lang——包含一些Java语言的核心类,如String、Math、Integer、System、Thread,提供常用的功能
  2. java.net——包含执行与网络有关的操作的类和接口
  3. java.io——包含能提供多种输入/输出功能的类
  4. java.uti——包含实用工具类,如定义系统的特性、接口的集合框架类、使用与日期日历相关的函数
  5. java.text——包含了一些java格式化相关的类
  6. java.sql——包含java进行JDBC数据库编程的相关类/接口
  7. java.awt——包含构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)
  8. java.applet——包含applet运行所需
  • this和super的区别:

名称thissuper
访问属性访问本类中的属性,如果本类没有此属性则从父类中继续查找访问本类中的属性
调用方法访问本类中的方法直接访问父类中的方法
调用构造器调用本类构造器,必须放在构造器的首行调用父类构造器,必须放在子类构造器的首行
特殊表示当前对象(仅在本类中表示对自己的引用)无此概念(仅在子类中表示父类的引用)
  • JUnit

/**JUnit    [当前project->Build Path -> Add Libraries -> JUnit ->JUnit5 -> Finish]
*/

//实际代码
import org.junit.Test;

@Test
public void test(){
    System.out.println("Hello World!");
}

/**测试
run as -> JUnit Test
*/
  • 关键字static  ——  静态,修饰属性、方法、代码块(初始化块)、内部类

  1. static修饰属性(类变量)—— 存放在静态域

             ①由类创建的所有对象,都共用此属性;

             ②当其中一个对象对此属性修改,会导致其他属性对此属性的一个调用。VS  实例变量(非static修饰的属性,各自对 应一套属于自己的副本);

             ③类变量随着类的加载而加载,且独一无二;

             ④可通过对象直接访问static变量(类名.变量名);

             ⑤static类变量的加载早于对象的加载(创建对象之后,可以调用static变量,不能调用实例变量)。

      2. static修饰方法(类方法) —— 存放在静态域

             ①随着类的加载而加载,在内存中独一无二;

             ②可以通过“类名.类方法”调用;

             ③内部可以调用静态的属性或静态的方法,而不能调用非静态的方法;反之,非静态的方法可调用静态的方法或属性(注:静态结构的生命要早于非静态的结构,同时被回收也晚于非静态结构,“生命周期更长”)

             ④静态的方法内不可有this或super关键字

//*******************************单例模式(Singleton)*******************************

<!--设计模式
在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。
-->

<!--单例设计模式
    采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
    如果要让类在一个虚拟机中只产生一个对象,我们首先必须将类的构造方法的访问设置为private,这样就不能用new操作符在类外部产生类的对象了,但在类内部仍可以产生该类的对象。
    因为在类外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,
    静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。
-->

/**
 * 单例设计模式: 
 * 1、解决:一个类只能创建一个对象
 */
public class SingletonTest {
	public static void main(String[] args) {
		// 饿汉式
		Singleton_hunger s1 = Singleton_hunger.getInstance();
		Singleton_hunger s2 = Singleton_hunger.getInstance();
		System.out.println(s1 == s2);// true
		
		//懒汉式——可能存在线程安全问题
		Singleton_lazy s3 = Singleton_lazy.getInstance();
		Singleton_lazy s4 = Singleton_lazy.getInstance();
		System.out.println(s3 == s4);// true

	}

}

// 只能创建单个实例————饿汉式
class Singleton_hunger {

	// 1、私有化构造器,在类外部不能调用此构造器
	private Singleton_hunger() {
		// TODO Auto-generated constructor stub
	}

	// 2、在类内部创建一个类的实例
	private static Singleton_hunger instance = new Singleton_hunger();

	// 3、私有化对象,通过公共的方法来调用
	// 4、此公共方法,只能通过类来调用,因其为static修饰,同时类的实例也必须为static声明的
	public static Singleton_hunger getInstance() {
		return instance;
	}
}

// 懒汉式
class Singleton_lazy {
	//1、
	private Singleton_lazy() {

	}
	//2、
	private static Singleton_lazy instance = null;
	//3、
	public static Singleton_lazy getInstance() {

		if (instance == null) {
			instance = new Singleton_lazy();
		}
		return instance;
	}
}

             ⑥main()方法 ——  主方法、程序的入口

//亦可作一般方法使用
public static void main(String[] args) {
		for (int i = 0; i < args.length; ++i) {
			args[i] = " " + i;
			System.out.println(args[i]);
		}
	}

      3. static修饰代码块 —— 静态代码块

             ①可以有输出语句

             ②可以对类的属性、类的声明进行初始化操作

             ③不可以对非静态的属性初始化(不能调用非静态的属性和方法)

             ④若有多个静态的代码块,则按照从上往下的顺序依次执行

             ⑤静态代码块的执行要先于非静态代码块

             ⑥静态代码块只能执行一次

      3.1 无static修饰的代码块 —— 非静态代码块

             ①可以有输出语句

             ②可以对类的属性、类的声明进行初始化操作

             ③可以调用静态的变量或方法

             ④若有多个静态的代码块,则按照从上往下的顺序依次执行

             ⑤每次创建对象时,都会执行一次。(先于构造器执行)

static{
    System.out.println("this is a static code!");
}

{
    System.out.println("this is not  a static code!");
}

/**
属性的赋值:
①默认的初始化; 
②显式的初始化或代码块初始化(两个结构按照顺序执行); 
③构造器中; 
④通过方法对对象的相应属性进行修改
*/

 

  • 关键字  final  ——  声明类、属性、方法(最终的)

  1. final标记的不能被继承(提高安全行,提高程序的可读性)e.g.String、System、StringBuffer
  2. final标记的方法不能被子类重写;  e.g.Object类中的getClass()
  3. final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只能被赋值一次。【final标记的成员变量必须在声明的同时或在每个构造方法中或代码块中显式赋值,然后才能使用】
常量赋值:①此常量不能使用默认初始化;②可以显式的赋值、代码块、构造器
变量用static、final修饰:全局变量

 

【注】

本文章属个人整理学习使用,如有不当之处望联系指正或删除。

【学习视频来源】尚硅谷http://www.atguigu.com/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值