1.基本概念
对象:对象表示现实世界中一个具体的事物。对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
类:类是一个模板,它描述一类对象的行为和状态。
举个例子:
生产每辆汽车都要按照图纸,经过生产组装,最终加工而成。而同样的车型,原始的生产图纸是同一个。那么这张生产图纸就相当于类。而生产出的具体的每辆车就相当于对象。类有一个,根据类实例化的对象可以有多个。类和对象就是这种关系。
再比如:
某某大学表白墙找对象的公告上写到这些条件“170cm以上的女生、学习好、会做饭、打篮球…”。
那么正巧一个名叫石榴姐的女孩说具备这个条件,而石榴姐是客观存在的事物,她就是对象(Object)。而这些条件就是一个类(Class),类是确定对象拥有的特征(属性)和行为(方法),它不是具体客观存在的东西。
- 类与对象的关系:
类是抽象的概念,仅仅是一个模板,比如说:“人”。
对象是一个你能够看得到、摸得着的具体实体。
类定义了对象将会拥有的特征(属性)和行为(方法)
类是对象的类型,对象是类的实例
- 类的使用步骤
创建一个Person类:
public class Person {
String name;
int age;
void eat() {
}
void sleep() {
}
}
创建Person对象:
public class Person {
String name;
int age;
void eat() {
}
void sleep() {
}
public static void main(String[] args) {
//创建Person对象
Person per = new Person();
//调用方法
per.eat();
}
}
一个类可以包含以下几种变量:
局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
类变量:类变量也声明在类中,方法体之外,但必须声明为static类型。
2.带参方法
概念:
例如,将榨汁机工作过程模拟到程序中:榨汁操作对应榨汁的方法;提供的水果原料对应方法参数;得到的果汁对应方法的返回值。传入不同的参数将得到不同的返回值。
- 带参方法的使用
1. 一个参数:
定义带参方法:
public class ZhazhiJi {
public String zhazhi ( String fruit ) {
String juice = fruit + "汁";
return juice;
}
}
}
调用带参方法:
/*调用zhazhi方法*/
ZhazhiJi myZhazhiji = new ZhazhiJi();
String myFruit = "苹果";
String myJuice = myZhazhi.zhazhi(myFruit);
System.out.println(myJuice);
2. 多个参数
定义带参方法:
public class ZhazhiJi {
public String zhazhi ( String fruit,String fruit2 ) {
String juice = fruit + "汁和"+fruit2+"汁";
return juice;
}
}
调用带参方法:
/*调用zhazhi方法*/
ZhazhiJi myZhazhiji = new ZhazhiJi();
String myFruit = "苹果";
String myFruit2 = "桃子";
String myJuice = myZhazhi.zhazhi(myFruit,myFruit2);
System.out.println(myJuice);
3. 构造方法
构造方法作用就是对类进行初始化。每个类都有构造方法。如果没有显式地为类定义构造方法,Java编译器将会为该类提供一个默认不带任何参数的构造方法。
在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法。
例子如下:
class Person //人类{
public Person(String n,int a) //构造方法
{
name = n; age = a;
}
private string name;
private int age;
}
public static void main(String[] args){
Person p = new Person("张三",14);//这就是作用
}
new一个对象的时候要用到构造函数,例如Hello hello = new Hello();这时调用的是Hello的无参数构造方法。
Hello hello = new Hello(“hi”);这个是调用Hello的有参数构造方法。
在JAVA中如果不写构造方法的话,会默认加上一个无参数的构造方法,但是如果已经有了一个有参数的构造方法,那么无参数的构造方法就不会默认被加上。
如果Hello类中已经有了一个有参数的构造方法,这时再使用 Hello hello = new Hello();来创建对象的时候就会出错,这就是为什么要强调写了有参数的构造方法就最好加一个无参数的构造方法。
- 方法的重载
在Java程序中,如果同一个类中存在两个方法同名,方法的签名(参数个数、参数类型、类型排列次序)上也一样,将无法编译通过。 但在Java中多个方法重名是允许的,只要保证方法签名不同即可,这种特性称为方法重载(overload)。
方法重载需遵循如下两条规则:
方法名相同;
参数列表(个数、类型、顺序)不同;
注意:返回值不影响方法重载。
构造方法也可以重载 。
以下实例演示了如何重载 MyClass 类的 info 方法:
class MyClass {
int height;
MyClass() {
System.out.println("无参数构造函数");
height = 4;
}
MyClass(int i) {
System.out.println("房子高度为 " + i + " 米");
height = i;
}
void info() {
System.out.println("房子高度为 " + height + " 米");
}
void info(String s) {
System.out.println(s + ": 房子高度为 " + height + " 米");
}
}
public class MainClass {
public static void main(String[] args) {
MyClass t = new MyClass(3);
t.info();
t.info("重载方法");
//重载构造函数
new MyClass();
}
}
以上代码运行输出结果为:
房子高度为 3 米
房子高度为 3 米
重载方法: 房子高度为 3 米
无参数构造函数
- 访问修饰符
Java中定义了private(私有的)、protected(受保护的)和public(公共的)的访问修饰符,同时也定义了一个缺省的访问级别,用于声明类、属性、方法的访问权限。
使用public访问修饰符,类的成员可被同一包或不同包中的所有类访问,也就是说,public访问修饰符可以使类的特性公用于任何类;
使用protected访问修饰符允许类本身、同一包中的所有类和不同包中的子类访问;
如果一个类或类的成员前没有任何访问修饰符时,它们获得缺省的访问权限,缺省的可以被同一包中的其他类访问;
private访问修饰符是限制性最大的一种访问修饰符,被声明为private的成员只能被此类中的其他成员访问,不能在类外看到。
实例:
首先,定义MyClass1类结构:
public class MyClass1 {
public int a = 5;
private int b = 10;
protected int c = 20;
int d = 30;
public void func1() {
System.out.println("func1");
}
private void func2() {
System.out.println("func2");
System.out.println(b);
}
protected void func3() {
System.out.println("func3");
}
void func4() {
System.out.println("func4");
}
}
然后,定义MyClass2类结构:
class MyClass2 {
public void func1() {
System.out.println("func1 of MyClass2");
}
}
最后,定义Test类,假如将Test类放在与MyClass1和MyClass2同一个包p1下,在Test中访问MyClass1、MyClass2及其成员的可行性如下 :
public class Test {
public void func() {
MyClass1 obj1 = new MyClass1();
System.out.println(obj1.a); // 公共属性,任何地方都可以访问 System.out.println(obj1.b); // Error,私有属性类外无法访问 System.out.println(obj1.c); // 受保护属性同包的类或子类可以访问 System.out.println(obj1.d); // 缺省属性同包的类可以访问 obj1.func1(); // 公共方法,任何地方都可以访问
obj1.func2(); // Error,私有方法类外无法访问
obj1.func3(); // 受保护方法同包的类或子类可以访问
obj1.func4(); // 缺省方法同包的类可以访问
MyClass2 obj2 = new MyClass2(); // 同一包中的缺省类可以访问
}
}
假如将Test类放在与MyClass1和MyClass2不同的包下,在Test中访问MyClass1、MyClass2及其成员的可行性如下 :
public class Test {
public void func() {
MyClass1 obj1 = new MyClass1();
System.out.println(obj1.a); // 公共属性,任何地方都可以访问
System.out.println(obj1.b); // Error,私有属性类外无法访问
System.out.println(obj1.c); // Error,受保护属性同包的类或子类才可以访问
System.out.println(obj1.d); // Error,缺省属性同包的类才可以访问
obj1.func1(); // 公共方法,任何地方都可以访问
obj1.func2(); // Error,私有方法类外无法访问
obj1.func3(); // Error,受保护方法同包的类或子类才可以访问
obj1.func4(); // Error,缺省方法同包的类才可以访问
MyClass2 obj2 = new MyClass2(); // 缺省访问级别同包才可以访问
}
}
假如Test类继承了MyClass1,并且不在同一个包下,在Test中访问MyClass1、MyClass2及其成员的可行性如下 :
public class Test extends MyClass1{
public void func() {
System.out.println(a); // 公共属性,任何地方都可以访问 System.out.println(b); // Error,私有属性类外无法访问 System.out.println(c); // 受保护属性同包的类或子类可以访问 System.out.println(d); // Error,缺省属性同包的类才可以访问 func1(); // 公共方法,任何地方都可以访问
func2(); // Error,私有方法类外无法访问
func3(); // 受保护方法同包的类或子类可以访问
func4(); // Error,缺省方法同包的类才可以访问
MyClass2 obj2 = new MyClass2(); // 缺省访问级别同包才可以访问
}
}
4. 继承
继承需要符合的关系是:is-a,父类更通用,子类更具体。
子类会具有父类的一般特性也会具有自身的特性。
使用继承优化设计:
优化后:
子类与父类的关系是is-a的关系,或者说是一种特殊和一般的关系。
例如Dog is a Pet。同样可以让学生继承人,让苹果继承水果,让三角形继承几何图形。
- Java中的继承
继承是Java面向对象编程技术的一块基石,它允许创建分等级层次的类。运用继承,可以创建一个通用类定义一系列一般特性。该类可以被更具体的类继承。
被继承的类称为父类
继承父类的类称为子类
执行继承时,子类将获得父类的属性,并具有自身特有的属性。
extends关键字用于继承类。声明一个继承父类的类的通常形式如下:
class 父类 {
}
class 子类 extends 父类 {
}
注意:
没有extends,默认父类为Object
只能有一个父类,即单继承
子类继承父类的全部成员,除了private成员
子类与父类不在同包,使用默认访问权限的成员不能被继承
构造方法不能被继承
例如:
开发动物类,其中动物分别为企鹅以及老鼠,要求如下:
企鹅:属性(姓名,id),方法(吃,睡,自我介绍)
老鼠:属性(姓名,id),方法(吃,睡,自我介绍)
企鹅类:
public class Penguin {
private String name;
private int id;
public Penguin(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
老鼠类:
public class Mouse {
private String name;
private int id;
public Mouse(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
从这两段代码可以看出来,代码存在重复了,导致后果就是代码量大且臃肿,而且维护性不高(维护性主要是后期需要修改的时候,就需要修改很多的代码,容易出错),所以要从根本上解决这两段代码的问题,就需要继承,将两段代码中相同的部分提取出来组成 一个父类。
公共父类:
public class Animal {
private String name;
private int id;
public Animal(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
这个Animal类就可以作为一个父类,然后企鹅类和老鼠类继承这个类之后,就具有父类当中的属性和方法,子类就不会存在重复的代码,维护性也提高,代码也更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码) 继承之后的代码:
企鹅类:
public class Penguin extends Animal {
public Penguin(String myName, int myid) {
super(myName, myid);
}
}
老鼠类:
public class Mouse extends Animal {
public Mouse(String myName, int myid) {
super(myName, myid);
}
}
- 继承的类型和特性
Java 不支持多继承,但支持多重继承。
继承的特性:
子类拥有父类非 private 的属性、方法。
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
子类可以用自己的方式实现父类的方法。
Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
super与this
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
例如:
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
输出结果:
animal : eat
dog : eat
animal : eat
final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:
声明类:
final class 类名 {//类体}
声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
- 构造方法继承
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
例如:
class SuperClass {
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
// SubClass 类继承
class SubClass extends SuperClass{
private int n;
SubClass(){ // 自动调用父类的无参数构造器
System.out.println("SubClass");
}
public SubClass(int n){
super(300); // 调用父类中带有参数的构造器
System.out.println("SubClass(int n):"+n);
this.n = n;
}
}
// SubClas2 类继承
class SubClass2 extends SuperClass{
private int n;
SubClass2(){
super(300); // 调用父类中带有参数的构造器
System.out.println("SubClass2");
}
public SubClass2(int n){ // 自动调用父类的无参数构造器
System.out.println("SubClass2(int n):"+n);
this.n = n;
}
}
public class TestSuperSub{
public static void main (String args[]){
System.out.println("------SubClass 类继承------");
SubClass sc1 = new SubClass();
SubClass sc2 = new SubClass(100);
System.out.println("------SubClass2 类继承------");
SubClass2 sc3 = new SubClass2();
SubClass2 sc4 = new SubClass2(200);
}
}
输出结果为:
------SubClass 类继承------
SuperClass()
SubClass
SuperClass(int n)
SubClass(int n):100
------SubClass2 类继承------
SuperClass(int n)
SubClass2
SuperClass()
SubClass2(int n):200
5.包
- 为什么需要包
Windows树形文件系统:
文档分门别类,易于查找和管理
使用目录解决文件同名冲突问题
Java中的包:解决类的同名问题。
- 包的创建
Java允许使用包将多个类组织在一起。借助于包可以方便的组织管理类,并将自定义的类与其它的类库分开管理。Java就是使用包来管理类库的 。 使用包维护类库比较简单,只要保证在同一个包下不存在同名的类即创建一个包也比较简单:只要将package命令作为一个Java源文件的第一句就可以,该文件中定义的任何类将属于指定的包。
用package声明包,以分号结尾。
作为Java程序的第一条语句。
package com.hyg.classandobject; //声明包 package后面是包名
public class School {
//……
public String toString() {
//……
}
}
- 包中类的访问
一个类可以访问其所在包的所有类。访问其他包的类有如下两种方式访问 :
使用import语句导入要访问的类 ,如:
import java.util.*;
import mypackage.school.Student ;
使用的类名前直接添加完整的包名 ,如:
java.util.Date now = new java.util.Date();
mypackage.school.Student tom = new mypackage.school.Student();
注意:* 指明导入当前包的所有类,不能使用类似于java. * 的语句来导入以java为前缀的所有包的所有类。
- 包的命名规范
包名由小写字母组成,不能以圆点开头或结尾
包名之前最好加上唯一的前缀,通常使用组织倒置的网络域名
package net.javagroup.mypackage;
包名后续部分依不同机构内部的规范不同而不同
package net.javagroup.research.powerproject;