java-封装

Java 封装

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。java

封装能够被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。shell

要访问该类的代码和数据,必须经过严格的接口控制。编程

封装最主要的功能在于咱们能修改本身的实现代码,而不用修改那些调用咱们代码的程序片断。windows

适当的封装可让程式码更容易理解与维护,也增强了程式码的安全性。安全

封装的优势

  • 1. 良好的封装可以减小耦合。编程语言

  • 2. 类内部的结构能够自由修改。ide

  • 3. 能够对成员变量进行更精确的控制。函数

  • 4. 隐藏信息,实现细节。测试

实现Java封装的步骤

1. 修改属性的可见性来限制对属性的访问(通常限制为private),例如:

public class Person {
    private String name;
    private int age;
}
这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其余类都访问不了,如此就对信息进行了隐藏。

2. 对每一个值属性提供对外的公共方法访问,也就是建立一对赋取值方法,用于对私有属性的访问,例如:

public class Person{
    private String name;
    private int age;
​
    public int getAge(){
      return age;
    }
​
    public String getName(){
      return name;
    }
​
    public void setAge(int age){
      this.age = age;
    }
​
    public void setName(String name){
      this.name = name;
    }
}
采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。

 

实例

让咱们来看一个java封装类的例子:this

EncapTest.java 文件代码:
/* 文件名: EncapTest.java */
public class EncapTest{
 
   private String name;
   private String idNum;
   private int age;
 
   public int getAge(){
      return age;
   }
 
   public String getName(){
      return name;
   }
 
   public String getIdNum(){
      return idNum;
   }
 
   public void setAge( int newAge){
      age = newAge;
   }
 
   public void setName(String newName){
      name = newName;
   }
 
   public void setIdNum( String newId){
      idNum = newId;
   }
}
以上实例中public方法是外部类访问该类成员变量的入口。

一般状况下,这些方法被称为getter和setter方法。

所以,任何要访问类中私有成员变量的类都要经过这些getter和setter方法。

经过以下的例子说明EncapTest类的变量怎样被访问:

RunEncap.java 文件代码:
/* F文件名 : RunEncap.java */
public class RunEncap{
   public static void main(String args[]){
      EncapTest encap = new EncapTest();
      encap.setName("James");
      encap.setAge(20);
      encap.setIdNum("12343ms");
 
      System.out.print("Name : " + encap.getName()+ 
                             " Age : "+ encap.getAge());
    }
}
以上代码编译运行结果以下:

Name : James Age : 20

 

Java 接口

接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口一般以interface来声明。一个类经过继承接口的方式,从而来继承接口的抽象方法。

接口并非类,编写接口的方式和类很类似,可是它们属于不一样的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

除非实现接口的类是抽象类,不然该类要定义接口中的全部方法。

接口没法被实例化,可是能够被实现。一个实现接口的类,必须实现接口内所描述的全部方法,不然就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们能够成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口与类类似点:

  • 一个接口能够有多个方法。
  • 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
  • 接口的字节码文件保存在 .class 结尾的文件中。
  • 接口相应的字节码文件必须在与包名称相匹配的目录结构中。

接口与类的区别:

  • 接口不能用于实例化对象。
  • 接口没有构造方法。
  • 接口中全部的方法必须是抽象方法。
  • 接口不能包含成员变量,除了 static 和 final 变量。
  • 接口不是被类继承了,而是要被类实现。
  • 接口支持多继承。

接口特性

  • 接口中每个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其余修饰符都会报错)。
  • 接口中能够含有变量,可是接口中的变量会被隐式的指定为 public static final 变量(而且只能是 public,用 private 修饰会报编译错误)。
  • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

抽象类和接口的区别

  • 1. 抽象类中的方法能够有方法体,就是能实现方法的具体功能,可是接口中的方法不行。
  • 2. 抽象类中的成员变量能够是各类类型的,而接口中的成员变量只能是 public static final 类型的。
  • 3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是能够有静态代码块和静态方法。
  • 4. 一个类只能继承一个抽象类,而一个类却能够实现多个接口。

接口的声明

接口的声明语法格式以下:

[可见度] interface 接口名称 [extends 其余的接口名名] {
        // 声明变量
        // 抽象方法
}
Interface关键字用来声明一个接口。下面是接口声明的一个简单例子。

NameOfInterface.java 文件代码:
/* 文件名 : NameOfInterface.java */
import java.lang.*;
//引入包
 
public interface NameOfInterface
{
   //任何类型 final, static 字段
   //抽象方法
}

接口有如下特性:

  • 接口是隐式抽象的,当声明一个接口的时候,没必要使用abstract关键字。
  • 接口中每个方法也是隐式抽象的,声明时一样不须要abstract关键字。
  • 接口中的方法都是公有的。
实例
Animal.java 文件代码:
/* 文件名 : Animal.java */
interface Animal {
   public void eat();
   public void travel();
}

 

接口的实现

当类实现接口的时候,类要实现接口中全部的方法。不然,类必须声明为抽象的类。

类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。

实现一个接口的语法,可使用这个公式:...implements 接口名称[, 其余接口名称, 其余接口名称..., ...] ...

实例
MammalInt.java 文件代码:
/* 文件名 : MammalInt.java */
public class MammalInt implements Animal{
 
   public void eat(){
      System.out.println("Mammal eats");
   }
 
   public void travel(){
      System.out.println("Mammal travels");
   } 
 
   public int noOfLegs(){
      return 0;
   }
 
   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}
以上实例编译运行结果以下:

Mammal eats
Mammal travels

重写接口中声明的方法时,须要注意如下规则:

  • 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
  • 类在重写方法时要保持一致的方法名,而且应该保持相同或者相兼容的返回值类型。
  • 若是实现接口的类是抽象类,那么就不必实现该接口的方法。

在实现接口的时候,也要注意一些规则:

  • 一个类能够同时实现多个接口。
  • 一个类只能继承一个类,可是能实现多个接口。
  • 一个接口能继承另外一个接口,这和类之间的继承比较类似。

接口的继承

一个接口能继承另外一个接口,和类之间的继承方式比较类似。接口的继承使用extends关键字,子接口继承父接口的方法。

下面的Sports接口被Hockey和Football接口继承:

// 文件名: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}
 
// 文件名: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}
 
// 文件名: Hockey.java
public interface Hockey extends Sports
{
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}
Hockey接口本身声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类须要实现六个方法。

类似的,实现Football接口的类须要实现五个方法,其中两个来自于Sports接口。

 

接口的多继承

在Java中,类的多继承是不合法,但接口容许多继承。

在接口的多继承中extends关键字只须要使用一次,在其后跟着继承接口。 以下所示:

public interface Hockey extends Sports, Event

以上的程序片断是合法定义的子接口,与类不一样的是,接口容许多继承,而 Sports及 Event 可能定义或是继承相同的方法

标记接口

最经常使用的继承接口是没有包含任何方法的接口。

标记接口是没有任何方法和属性的接口.它仅仅代表它的类属于一个特定的类型,供其余代码来测试容许作一些事情。

标记接口做用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。

例如:java.awt.event 包中的 MouseListener 接口继承的 java.util.EventListener 接口定义以下:

package java.util;
public interface EventListener
{}

没有任何方法的接口被称为标记接口。标记接口主要用于如下两种目的:

  • 创建一个公共的父接口:

    正如EventListener接口,这是由几十个其余接口扩展的Java API,你可使用一个标记接口来创建一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。

  • 向一个类添加数据类型:

    这种状况是标记接口最初的目的,实现标记接口的类不须要定义任何接口方法(由于标记接口根本就没有方法),可是该类经过多态性变成一个接口类型。

java 包(package)

为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。

包的做用

  • 一、把功能类似或相关的类或接口组织在同一个包中,方便类的查找和使用。

  • 二、如同文件夹同样,包也采用了树形目录的存储方式。同一个包中的类名字是不一样的,不一样的包中的类的名字是能够相同的,当同时调用两个不一样包中相同类名的类时,应该加上包名加以区别。所以,包能够避免名字冲突。

  • 三、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。

包语句的语法格式为:package pkg1[pkg2[pkg3]];

例如,一个Something.java 文件它的内容

package net.java.util;
public class Something{
   ...
}

那么它的路径应该是 net/java/util/Something.java 这样保存的。 package(包) 的做用是把不一样的 java 程序分类保存,更方便的被其余 java 程序调用。

一个包(package)能够定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。

如下是一些 Java 中的包:

  • java.lang-打包基础的类
  • java.io-包含输入输出功能的函数

开发者能够本身把一组类和接口等打包,并定义本身的包。并且在实际开发中这样作是值得提倡的,当你本身完成类的实现以后,将相关的类分组,可让其余的编程者更容易地肯定哪些类、接口、枚举和注释等是相关的。

因为包建立了新的命名空间(namespace),因此不会跟其余包中的任何名字产生命名冲突。使用包这种机制,更容易实现访问控制,而且让定位相关类更加简单。

建立包

建立包的时候,你须要为这个包取一个合适的名字。以后,若是其余的一个源文件包含了这个包提供的类、接口、枚举或者注释类型的时候,都必须将这个包的声明放在这个源文件的开头。

包声明应该在源文件的第一行,每一个源文件只能有一个包声明,这个文件中的每一个类型都应用于它。

若是一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中。

例子
让咱们来看一个例子,这个例子建立了一个叫作animals的包。一般使用小写的字母来命名避免与类、接口名字的冲突。

在 animals 包中加入一个接口(interface):

Animal.java 文件代码:
/* 文件名: Animal.java */
package animals;
 
interface Animal {
   public void eat();
   public void travel();
}
接下来,在同一个包中加入该接口的实现:

MammalInt.java 文件代码:
package animals;
 
/* 文件名 : MammalInt.java */
public class MammalInt implements Animal{
 
   public void eat(){
      System.out.println("Mammal eats");
   }
 
   public void travel(){
      System.out.println("Mammal travels");
   } 
 
   public int noOfLegs(){
      return 0;
   }
 
   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}
而后,编译这两个文件,并把他们放在一个叫作animals的子目录中。 用下面的命令来运行:

$ mkdir animals
$ cp Animal.class  MammalInt.class animals
$ java animals/MammalInt
Mammal eats
Mammal travel

 

import 关键字

为了可以使用某一个包的成员,咱们须要在 Java 程序中明确导入该包。使用 "import" 语句可完成此功能。

在 java 源文件中 import 语句应位于 package 语句以后,全部类的定义以前,能够没有,也能够有多条,其语法格式为:

import package1[.package2].(classname|*);

若是在一个包中,一个类想要使用本包中的另外一个类,那么该包名能够省略。

例子
下面的 payroll 包已经包含了 Employee 类,接下来向 payroll 包中添加一个 Boss 类。Boss 类引用 Employee 类的时候能够不用使用 payroll 前缀,Boss类的实例以下。

Boss.java 文件代码:
package payroll;
 
public class Boss
{
   public void payEmployee(Employee e)
   {
      e.mailCheck();
   }
}
若是 Boss 类不在 payroll 包中又会怎样?Boss 类必须使用下面几种方法之一来引用其余包中的类。

使用类全名描述,例如:

payroll.Employee
用 import 关键字引入,使用通配符 "*"

import payroll.*;
使用 import 关键字引入 Employee 类:

import payroll.Employee;
注意:

类文件中能够包含任意数量的 import 声明。import 声明必须在包声明以后,类声明以前。

package 的目录结构

类放在包中会有两种主要的结果:

  • 包名成为类名的一部分,正如咱们前面讨论的同样。
  • 包名必须与相应的字节码所在的目录结构相吻合。
下面是管理你本身 java 中文件的一种简单方式:

将类、接口等类型的源码放在一个文本中,这个文件的名字就是这个类型的名字,并以.java做为扩展名。例如:

// 文件名 :  Car.java
 
package vehicle;
 
public class Car {
   // 类实现  
}
接下来,把源文件放在一个目录中,这个目录要对应类所在包的名字。

....\vehicle\Car.java
如今,正确的类名和路径将会是以下样子:

类名 -> vehicle.Car

路径名 -> vehicle\Car.java (在 windows 系统中)

一般,一个公司使用它互联网域名的颠倒形式来做为它的包名.例如:互联网域名是 runoob.com,全部的包名都以 com.runoob 开头。包名中的每个部分对应一个子目录。

例如:有一个 com.runoob.test 的包,这个包包含一个叫作 Runoob.java 的源文件,那么相应的,应该有以下面的一连串子目录:

....\com\runoob\test\Runoob.java
编译的时候,编译器为包中定义的每一个类、接口等类型各建立一个不一样的输出文件,输出文件的名字就是这个类型的名字,并加上 .class 做为扩展后缀。 例如:

// 文件名: Runoob.java
 
package com.runoob.test;
public class Runoob {
      
}
class Google {
      
}
如今,咱们用-d选项来编译这个文件,以下:

$javac -d . Runoob.java
这样会像下面这样放置编译了的文件:

.\com\runoob\test\Runoob.class
.\com\runoob\test\Google.class
你能够像下面这样来导入全部 \com\runoob\test\ 中定义的类、接口等:

import com.runoob.test.*;
编译以后的 .class 文件应该和 .java 源文件同样,它们放置的目录应该跟包的名字对应起来。可是,并不要求 .class 文件的路径跟相应的 .java 的路径同样。你能够分开来安排源码和类的目录。

<path-one>\sources\com\runoob\test\Runoob.java
<path-two>\classes\com\runoob\test\Google.class
这样,你能够将你的类目录分享给其余的编程人员,而不用透露本身的源码。用这种方法管理源码和类文件可让编译器和java 虚拟机(JVM)能够找到你程序中使用的全部类型。

类目录的绝对路径叫作 class path。设置在系统变量 CLASSPATH 中。编译器和 java 虚拟机经过将 package 名字加到 class path 后来构造 .class 文件的路径。

<path- two>\classes 是 class path,package 名字是 com.runoob.test,而编译器和 JVM 会在 <path-two>\classes\com\runoob\test 中找 .class 文件。

一个 class path 可能会包含好几个路径,多路径应该用分隔符分开。默认状况下,编译器和 JVM 查找当前目录。JAR 文件按包含 Java 平台相关的类,因此他们的目录默认放在了 class path 中。

设置 CLASSPATH 系统变量

用下面的命令显示当前的CLASSPATH变量:

  • Windows 平台(DOS 命令行下):C:\> set CLASSPATH
  • UNIX 平台(Bourne shell 下):# echo $CLASSPATH

删除当前CLASSPATH变量内容:

  • Windows 平台(DOS 命令行下):C:\> set CLASSPATH=
  • UNIX 平台(Bourne shell 下):# unset CLASSPATH; export CLASSPATH

设置CLASSPATH变量:

    • Windows 平台(DOS 命令行下): C:\> set CLASSPATH=C:\users\jack\java\classes
    • UNIX 平台(Bourne shell 下):# CLASSPATH=/home/jack/java/classes; export CLASSPATH
相关文章
相关标签/搜索