面向对象封装

一.面向对象概念回顾

1. 面向对象的概念:目前来说要有一个整体的意识

2. 类:就是一个分类,类别,一般是描述现实中的事物.

例如:class Person{}  class Student{}等等

像我们写的Person Student自己写的类和java内库中的类性质是一样的(String Arrays Date

字符串对象String 他其实就是一个类  

3. 对象:实例,实体,类的个体

目前我们创建的时候象需要  new加类名()

4.是先有类还是先有对象?

在程序中是先有类 再有对象 new 类名()  没有这个类怎么new这个类的对象呢

5.练习:设计一个学生类,学生有属性和方法 (1.不要写主方法 2.以前写类都在一个class文件中 现在写一个必要单独的一个文件) 用测试类来测试创建学生类

 

一个简单的学生类和这个类的测试类就写好了

二.构造方法

1.什么是构造方法

构造方法就是一个类中来初始化对象的一个方法!这是每个类都拥有的。这么说可能大家不太清楚,当我们创建学生类对象的时候new Student(); 那么后面那个Student()就是学生类的构造方法。目前我们创建对象就是就是new关键字加上构造方法。我们一般方法的结构是:

public void eat() {}

public:权限--这个方法在什么地方能够被访问

void:这个方法的返回值类型 void代表方法没有任何的返回值;比如说打印一句话,并没有返回什么数据吧,像这样没有返回值的方法就用void。如果我们方法中要返回一个类型的值。比如:

public int get(){

return 1;

}

这个方法里面就return 返回了一个int类型的值 所以方法返回值类型用int

eat:方法的名字 随便取名,注意首字母跟变量名一样都是小写,变量名,方法名首字母都是小写。Java规定哈。我们的类名必须首字母大写,这点要注意

():括号里面是这个方法接收参数的 比如传一个参数进来

public int get(int a){

return a+1;

}

传一个int的值进来 我们返回这个值+1 当然可以传多个参数进来用逗号分隔

{}:方法实体--此方法具体做的事情 就是我们写代码的地方了

上面是普通方法的结构

我们构造方法的结构很简单跟普通方法可以对比一下:

public Student(){}

Student:是类名 这个名字不能随便取 乱取一个名就不是构造方法 他必须跟类名一模一样

public(){}跟普通方法一样哈 没什么可多说的

我们发现写法上的不同:少了一个什么,少了一个返回值类型对不对;因为我们的构造方法是没有返回值的 他不会返回一个值 注意哈

我们说过new一个对象就是调用这个对象的构造方法,那么我们并没有看到这个构造方法呢,在哪呢。首先肯定在这个类里边,我们没看到不代表没有哈,只是他是隐藏起来的,其实是有的哈

Student(){}

我们现在手动写出来这样能理解了吧 他方法实体没有任何内容的时候,那么就是专门给我们创建对象的

new Student()

看一下是不是new 加上这个构造方法

那么如果我们不手动写出来,java编译的时候自动给我们加上这个无参构造函数

总结:

1. 构造方法的名字和类名一致(包括大小写完全一样)

2. 没有返回值类型

3. 构造方法内部不需要返回任何数据

4. 可以手动写出来,如果不写,java会自动给我们加上(无参构造函数)

类中构造函数的特点:

1. 每一个类中都至少有一个构造函数

2. 没有看到的话就存在一个隐式的无参数的构造函数

3. 如果我们手动写了一个构造函数,那么隐式的就不存在了

现在我们验证一下new对象的时候是否在调用这个构造方法

首先隐式的构造方法没有实际内容,我们让它打印一句话,看new对象的时候是否执行了

Student() {

System.out.println("我是无参构造函数");

}

通过new对象,就打印了这句话,说明就是调用这个构造方法

现在我们来给学生类多加一些属性并创建对象,并把这个学生的属性赋上一些值

Student s = new Student();

s.name = "张三";

s.age = 20;

s.banji = 3;

s.gender = "";

s.phone = 18708001199L;

我们发现根据字段的变多,赋值的代码就越多,如果有100个字段,我们就要写100

这个时候我们想一下有没有优化的空间;想一下:我们的目的就是把学生类里面的属性赋值也就是nameage,等等 接下来我直接写出来,你们是否能看懂

我让它的构造函数做点事情

Student(String name1,int age1,int banji1,String gender1,Long phone1) {

name = name1;

age = age1;

banji = banji1;

gender = gender1;

phone = phone1;

}

这样赋值比前面一行一行的赋值要好得多

构造函数的好处:

1. 通过构造函数可以创建对象

2. 在创建对象的时候可以给对象的字段赋值

刚才我们手动写了一个可以传参数的构造函数,那么这个类就没有隐式的无参数构造函数了哈,就是编译的时候java也不会给我们加上了

所以记住:只要手动写了构造函数不管是有参的还是无参 只要手动写出来了 那么就没有隐式的无参构造函数

接下来我变一下:

public class Student {

void Student(){

System.out.println("hello");

}

}

new Student();

请问这样运行的时候会不会报错?

不仅没报错,还可以new这个对象:

首先这是不是一个构造函数,不是的嘛,构造函数在定义的时候是没有返回值类型的 void的意思并不是没有返回值类型,它的意思是这个方法的返回值类型是没有返回值类型,听上去有点饶啊 意思就是这个方法有返回值类型,但是你可以不返回任何数据。

那么所以说虽然方法名跟我们的类名是一样的,但是他定义了有返回值类型的方法,并不是这个类的构造函数 所以说这个类里面还有一个隐式的无参构造函数

注意:以后咱们定义方法的时候,千万不要像这样写一个跟类名一样的名字,容易混淆,而且我们定义方法首字母必定小写,这是行业规范;

三.匿名对象

1.什么是匿名对象?

从字面上理解,就是没有名字的对象。比如说

new Student();

这个请问大家能叫上名字吗?我们平时都是用一个变量来接收这个对象

Student s = new Student();

这个对象有名字吗?就是s嘛  s就相当于这个对象的名字

有了名字我们就可以对s这个对象的属性赋值,比如s.name=  s.age=

那一个匿名对象怎么给多个属性赋值啊?

new Student().name = “张三;

可以吗?可以,这样就给这个匿名对象的姓名赋值了,但是我还想给他的年龄赋值,这时候怎么办

new Student().name = "张三";

new Student().age = 29;

这样吗?不行哈。这两玩意是一个对象吗?不是啊注意了。我们new了两次相当于创建了两个对象,他们不是同一个对象啊。我想问,现在我要打印这个张三的对象的属性,怎么打印?

System.out.println(new Student().name);

这样又new了一个对象而且打印出来没值!

通过我们的观察:匿名对象只能使用一次,不给他取名,不给他用变量接收起来,我们就没办法使用他。

那么匿名对象对我们来说有什么意义,有什么用?

2.匿名对象的用处:当我们只需要访问一次类里面的成员(属性和方法)的时候,就可以用匿名对象

public void sleep(){

System.out.println("睡觉");

}

当我们只想调用一次类里面的睡觉方法就可以

new Student().sleep();

3. 匿名对象的生命周期

生命周期,就是一个对象存在到结束,或者说内存中存在到在内存中消失的时间

匿名对象的生命周期我们有两种说法:

1. 当我们new Student();的时候 这个对象就开始存在了 而当这个对象失去所有引用(就是没有变量来接收的时候,相当于失联了,相当于马航一样)这个对象就不存在了

2. new的时候开始,而结束的时候是这个对象在内存中真正被销毁的时候(咱们java有自动垃圾回收机制: 会在指定的时候 把那些内存的垃圾自动销毁)

所以说咱们的匿名对象是一个短命鬼啊,创建对象调用了一个方法就死了。好比说:孩子一下来,诶,哭一下,好拜拜了

四.static关键字 静态

1.static java 的关键字,是一个修饰符

我们学习一个东西 首先看它用在什么地方,然后看它有什么效果

static主要用途:可以修饰 字段 方法

2.static修饰变量:可以修饰成员变量,不可修饰局部变量

成员变量:作为一个类中的成员

public class Student {

String name;

}

局部变量:在方法里面定义的变量

public void asd(){

int i;

}

i就是局部变量

成员变量和局部变量主要看他们在什么地方定义的!

 

3. static修饰类:可以修饰内部类,不可修饰外部类

内部类:在类中还有一个类,以后会有所接触,现在暂时作一个了解

public class Student {

class Hehe{

}

}

没报错啊 这个Hehe就是内部类 在一个类的里边

那么Student就是外部类

 

4. static修饰方法和字段

咱们看主函数里面就有static修饰

static有什么用呢?

通过代码来看一下有什么用:

static String name;

int age;

public static void main(String[] args) {

Student s1 = new Student();

s1.name = "张三";

s1.age = 20;

Student s2 = new Student();

s2.name = "李四";

s2.age = 18;

System.out.println(s1.name);

System.out.println(s2.name);

}

怎么s1的姓名也成李四了 通过图来分析一下原因

 

---- ------- ------ --------- --------- -------- ------- ------- --------- ------ ----- -----

 

所以说:static修饰的字段是所有对象的共享数据。

什么时候用?比如:员工类,描述员工,有姓名,部门等 里面有一个地址的字段,当我们公司要搬的时候 地址要换 这时候一个员工要换地址 e1.adrees=“环球中心”;那么这个公司的所有员工的地址是不是都在环球中心了

当然实际开发中一般是用在:希望被所有对象共享的数据,比如在圆的类中,有直径,半径,还有π3.14这个3.14是所有圆的共享数据。

一般来说是全局常量使用static修饰居多 这个pi就是全局常量。

顺便提一下什么是全局常量:public static final double pi = 3.14;全局静态不可变的变量就是全局常量

所以static修饰字段的时候多是全局常量

 

现在来看看修饰方法:

主要作用:不用创建对象就可以访问 直接 类名.方法();

public class Student {

public void eat(){

System.out.println("...");

}

public static void sleep(){

System.out.println("睡觉");

}

public static void main(String[] args) {

Student s = new Student();

s.eat();

s.sleep();

Student.sleep();

}

}

一般不要用 对象 . 方法名 直接用 类名 . 方法名

因为这样人家一看就知道是静态方法;java规范

那么思考一下:学生类中的吃方法 应该用static修饰吗?

注:不应该,因为吃 是某个学生的具体对象来吃(是某个人在吃)

而且他们吃的东西并不一定一样,比如说你要吃包子,我要吃鲍鱼。你搞个静态的话,你一吃包子,我就跟着吃包子去了,这是不是对我来说太亏了;

static一般用在工具类,工具类中提供很多方法让我们使用,方法的功能弄好了一般不做改变,那么这时候就用静态修饰。如果不用静态,我们还得去new一个这个类的对象,在用对象 . 来调用方法。这个对象就多余了还占用内存;

所以放在静态区的就可以直接 类名.成员;来访问

5.静态访问静态,静态不能访问非静态

public class Student {

String name="张三";

public static void main(String[] args) {

System.out.println(name);

}

}

打印不了,我们的主函数有static修饰,所以他是静态方法,静态不能访问非静态的,相当于静态区里边的东西可以互相访问(静态访问静态),而静态区不能访问堆内存里边的字段name;这时候把name加一个static就可以访问了

五.包

包这个词大家应该都清楚。钱包,书包,皮包,包的英文:package

那么java中的包就是这个关键字,java的包什么意思呢?

比如我们平时放电影资源的时候,分一个类,比如我们平时装电影的时候:

 

我们用文件夹一层一层地给电影做分层管理,方便我们查找和管理;

那么java中的包就是文件夹的意思,也是一层一层的比如说:

新建一个包cn.modengxian.java

再新建一个class

我们看到每个文件最上面都有一个package ……..

我们去找到这个类的class文件

我们看到cn.modengxian.java 在系统中就是一层一层的文件夹

包的作用:1.可以管理代码结构   2.可以避免类名冲突的问题,比如在一包中建两个同名的类是不行的,如果说我业务需求,刚好两个类的名字是一样,这时候就把它们放到不同的包中就可以同时存在了,相当于在一个文件夹中能有同名相同的文件吗?一样的道理啊

1. 如何定义包

一般是公司域名反过来写+项目名+模块名字+子模块名

比如公司的域名是:itsource.com   项目叫shool (一个学校里的业务项目)模块叫study

那么包的名字就是:com.itsource.shool.study.domain 这个domain就是我们自己的子模块,专门放描述类的java文件 就是我们定义的类都放这里,实际开发中还有业务层,

com.itsource.shool.study.service 业务层 专门当完成业务功能的代码

我们来试一下定义两个包,在一包中访问另一个包中的类

 

现在我就是想创建一个java班的学生,怎么创建?这时候在new的时候就要写上在哪个包的哪个类new cn.modengxian.java.Student();这种写法就是全限定名

然后发现报错,为什么。这时候就介绍一个

2.public 权限关键字

在不同包中的访问,必须要加上public 我们把java中的name字段加上public就可以访问了,如果不加就访问不到哈。我们试着把类上面的public去掉,也一样不能new

我们用eclipse创建类的时候 人家自动给我们加上public,如果我们按照以前的写法,把多个类放在同一个java文件中

class Teacher{

}

如果我们想要不同包中都可以访问这个Teacher类我们就加上public! 嘿!!报错了,为什么呢?因为java规定!一个文件中只能存在一个public修饰的类。所以说我们要求每一个类都要有单独的文件,这样每一个类都能被外面访问。现在明白为什么要这么做了吧!

3.全限定名 和 导包

我们发现写全限定名太麻烦,太多了!这时候我们可以用导包的方式来优化代码!

比如新建一个Teacher

Cn.modengxian.ui.Teacher t = new cn.modengxian.ui.Teacher();

如果说我们要用new很多个老师对象,每次都要写这么长串。很麻烦。

这时候又有一个

4.关键字import

导入的意思,专门来导入我们要使用的那个包

import cn.modengxian.ui.Teacher;

导入进来就可以直接new Teacher();

注意:写在package和其他代码的中间  package下面

好,这时候比如说我们ui包下面有很多类,而且我现在还需要用到里面的很多类,我们是不是得一个个导入进来,像这样的情况 我们可以直接把这个包里面的所有类一次导进来。

写法:import cn.modengxian.ui.*;

比如说要同时用到相同类名的两个类,像我们的ui班的Student java班的Student

这时候我们就必须用全限定名来区分,虽然我们可以导包-不推荐!java的规范是让我们容易看明白,两个都有全限定名  我们一看就知道是不同包里面的同名类

我们来用一下java内库中的Arrays类  ,他是一个工具类,专门操作数组的一个类,里面方法全是静态static,所以我们直接Arrays.方法名

比如我们之前自己写了一个方法给数组排序,像这样比较常用的功能,java已经给我们提供了。来一个数组:

int [] arr = {3,15,4,31,5,32,1,66,8};

Arrays.sort(arr);

如何快速导包:

1. 类名直接代码提示; alt+/

2. ctrl+shift+o

六.面向对象-封装

面向对象三大特征之一:封装,继承,多台

什么是封装?我们之前饿了直接招一个保姆,调用保姆煮面的方法。我们关注的是煮面后的结果,至于她是如何煮面的过程,我们不用关心。这个保姆本身就把煮面的方法封装了。我们用的时候就用保姆这个对象.煮面()就行了。

像我们的电脑,我们要用电脑上网,我们不用关心它是如何运行,如何上网等,只要把整个机箱搬过来使用就行了。机箱里面封装了很多功能,有cpu,主板,网卡。这就是封装。

那么java中的封装,就要提到一个

1. private关键字

private是私有的意思,把我们不想对外共享的东西私有化。直接上代码

public class Student {

String name;

}

之前我们这样写,它也是有权限的,叫默认权限。如果在别的包中要访问这个字段,就得加一个public,我们现在加上private来试试

权限从大到小:public( 共有) > 默认权限 > protected(继承)>private(私有)

创建一个主函数,访问并赋值这个name字段

public class Student {

private String name;

public static void main(String[] args) {

Student s = new Student();

s.name = "asd";

System.out.println(s.name);

}

}

这个是没问题的,因为

2. private修饰过后,只能在本类中访问。

我们的主函数在本类中吧,所以是可以访问。我们在外边访问

public class Student {

private String name;

}

新建一个Test 文件类

public static void main(String[] args) {

Student s = new Student();

s.name = "asd";

System.out.println(s.name);

}

相当于Student封装到一个箱子里,在箱子里的成员可以互相访问,在箱子外面就访问不到箱子里边的东西;这就是封装!

那么我们思考;现在这个name字段被私有化了,我现在要在外面怎么给这个字段赋值呢?

当然不能直接用对象. 字段的方式来访问。这时候我们可以提供两个方法出去,这两个方法分别是给name赋值和取值的方法,首先这两个方法不能再用private了!如果全是private,那么这个Student就相当于一个铁皮盒子,完全密闭,里面有再多的属性,再好的功能,我们拿不到。总得提供一把钥匙出去,让外边能通过这个钥匙拿东西。

public void setName(String name1){

name = name1;

}

s.setName("张三");

就是把“张三”的字符串传到set方法的name1上面,再赋值给字段name上,最后 这个张三就赋值到字段name里去了! 然后再提供一个可以取值的方法

首先分析这个方法的返回值,需不需要传参数;

public String getName(){

return name;

}

我们调用这个方法就可以得到name字段里的数据了!

Student s = new Student();

s.setName("张三");

String name = s.getName();

System.out.println(name);

有人说,这样太麻烦,还要多写两个方法。我直接sname要方便得多,可是比如说:现在有一个篮球类:篮球类里边有一个属性是,type 形状。 private type=“圆形”;

如果我不加private 你过来new一个篮球把我们的形状改成方形。你说这个篮球还能玩吗?

那么我们描述篮球的时候,就是有一个type属性,而且不需要外面来改变。所以必须封装起来,而且我还不提供set方法,不让你设置嘛

所以以后定义类的属性,通通要加private   而且都要有getset方法,除非是不想让外面来改变的值。

有人问,为什么需要getset方法呢,我们可以直接写到一个方法里,这样少一个方法

public String name(String name1){

name  = name1;

return name;

}

可以是可以,但是,如果我现在只想要你能取值,不让你赋值。这一个方法就不够用了;

而且在java中方法的定义,你能干什么就干什么去,别干多余的事,各做各的事。我们好管理。

如果我们定义setName的时候是这样写

public void setName(String name){

name = name;

}

因为我们形参的变量名都可以随便取,如果形参名跟字段名一样。这样能不能给字段的name赋值?不行,这两个name都是用的形参的name都是我们传进来的数据装到这个name里,这里就是自己等于自己;是不是傻;那么这个时候怎么赋值;

3.关键字this

this代表本类的引用对象。

public void setName(String name){

this.name = name;

}

现在这个this.name就是字段上的name了,这个this就代表本类的引用对象,

Student s = new Student();

s.setName("张三");//this就代表这个s对象

 

Student s1 = new Student();

s1.setName("李四");//this就代表这个s1对象

这样java就能区分哪个name是字段,哪个是形参

4.本类中的构造函数相互调用

public class Student {

private String name;

private int age;

Student(String name){

this.name = name;

}

Student(String name,int age){

this.name = name;

this.age = age;

}

}

通过代码可以发现,两个构造函数都有同一个动作就是给name字段赋值。那么上边已经帮我们把name赋值,我现在也是给name赋值,那么可不可以我直接调用一下你的方法。让你把事做了;那么构造方法怎么调用构造方法。首先跟调用普通方法差不多;

Student(name);

报错了,java中不能这么调用构造方法的,除了new对象的时候。那么这里把Student换成thisname);这就调用了上面的构造方法;

5.所以this的用法:1.区分字段和其他变量--this.字段 2.调用本类的构造函数--this(形参)

6.说回来getter/setter的规范

String name;                                   特殊:boolean sex

getName()     setName(String name)              isSex()   setSex(boolean sex)

 

取名的规范,自己看了,自己总结!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值