JAVA面向对象
1.包
1.包(package) 是组织类的一种方式,使用包的主要目的是保证类的唯一性,package和import的区别在于:package是包,指类所在的包,import是引入,引入类中需要的类. 2.如下图代码所示,导入了一个具体的类,import能导入一个具体的类,例如:import java.util.Arrays,但是不能导入一个具体的包. 3.在import导入中我们也可以使用import java.util.*,其中*表示通配符,与C语言的#include不同,#include会将头文件中全部内容拿来使用,而JAVA是用到哪个类就使用哪个类。 4.更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况,如下图1.2所示代码。 |
//代码1.1
import java.util.Arrays;
public class test {
public static void main(String[] args) {
int[] arr={1,2,3,4,5};
System.out.println(Arrays.toString(arr));
}
}
//代码1.2
import java.util.*;
import java.sql.*;
public class Test {
public static void main(String[] args) {
// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
Date date = new Date();
System.out.println(date.getTime());
}
}
// 编译出错
Error:(5, 9) java: 对Date的引用不明确
java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配
1.1 包的创建
包的创建规则
- 在文件的最上方加上一个package语句指定该代码在哪个包
- 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.baidu.demo )
- 包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储代码
- 如果一个类没有 package 语句, 则该类被放到一个默认包中.
1.2 包的访问控制权限
我们已经了解了类中的 public 和 private. private中的成员只能被类的内部使用.
如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外部的类使用.
如下图代码所示,Demo1 和 Demo2 是同一个包中.
没有任何修饰符的权限就是包访问权限,意味着当前包的所有类都可以访问成员.
package com.bit.demo;
public class Demo1 {
int value = 10;
}
package com.bit.demo;
public class Demo2 {
public static void Main(String[] args) {
Demo1 demo = new Demo1();
System.out.println(demo.value);
}
}
// 执行结果, 能够访问到 value 变量 -> 10
2.继承
代码中创建的类, 主要是为了抽象现实中的一些事物(包含属性和方法).有的时候客观事物之间就存在一些关联关系, 那么在表示成类和对象的时候也会存在一定的关联.
比如我们创建动物类,代码如下图所示:
class Animal{
public int age;
public String name;
public void eat(){
System.out.println("eat()");
}
public Animal(String name,int age){
this.name=name;
this.age=age;
}
}
class Dog{
public int age;
public String name;
public void eat(){
System.out.println("eat()");
}
}
class Bird extends Animal{
public String wing;
public String name;
public void fly(){
System.out.println("fly()");
}
}
在上述的代码中,我们会发现出现了许多的冗余代码,Dog,Bird和Animal存在着关联,于是我们可以把它们的共性抽象出来,使用extends关键字可以继承Animal类,达到代码重用的效果.
Animal这样被继承的类, 我们称为父类,基类或超类, 对于像Cat和Bird这样的类, 我们称为子类,派生类.
2.1 继承的语法
class 子类 extends 父类 {
}
注意事项: 1.使用 extends 指定父类 2.Java 中一个子类只能继承一个父类 3.子类会继承父类的所有 public 的字段和方法,子类在使用构造方法时,会先构造父类 4.对于父类的 private 的字段和方法, 子类中是无法访问的 5.子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用 |
//使用extends后的代码
class Animal{
public int age;
public String name;
public void eat(){
System.out.println("eat()");
}
}
class Dog{
}
class Bird extends Animal{
public String wing;
public void fly(){
System.out.println("fly()");
}
}
2.2 继承的限制
不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系.
如果想从语法上进行限制继承, 就可以使用 final 关键字.
final 关键字, 修饰一个变量或者字段的时候, 表示常量不能修改.
final int a = 10;
a = 20; // 编译出错
final 关键字也能修饰类, 此时表示被修饰的类就不能被继承
final public class Animal {
...
}
public class Bird extends Animal {
...
}
// 编译出错
Error:java:无法进行继承
3.多态
3.1 多态的理解
多态 :通过一个引用调用同一个方法,会呈现出不同的表现
class Shape{
public void drawMap(){
;
}
}
class triangle extends Shape{
@Override
public void drawMap(){
System.out.println("△");
}
}
class circle extends Shape{
@Override
public void drawMap(){
System.out.println("○");
}
}
class star extends Shape{
@Override
public void drawMap() {
System.out.println("☆");
}
}
public class TEST{
public static void drawMap(Shape a){
a.draw();
}
public static void main(String[] args) {
Shape shape1=new circle();
shape1.drawMap();
star s1=new star();
drawMap(s1);
triangle s2=new triangle();
drawMap(s2);
}
}
参数类型为 Shape (父类), shape 引用指向的是不同类型的实例,shape 这个引用调用 draw 方法可能会有多种不同的表现这种行为就称为多态.
3.2 向上转型
class Animal{
public int age;
public String name;
public void eat(){
System.out.println("eat()");
}
public Animal(String name,int age){
this.name=name;
this.age=age;
}
}
class Dog extends Animal{
public Dog(String name,int age) {
super(name,age);
}
}
}
public class Test {
public static void main(String[] args) {
Animal animal=new Dog("haha",12);
System.out.println(animal.name);
}
}
其中
Animal animal=new Dog("haha",12);
此时 animal是一个父类 (Animal) 的引用, 指向一个子类 (Dog) 的实例.父类引用引用子类对象,这种写法称为向上转型.
向上转型发生的时机:1.直接赋值 2.方法传参 3.方法返回
public class Test {
public static void main(String[] args) {
Bird bird = new Bird("小鸟");
feed(bird);
}
public static void feed(Animal animal) {
animal.eat("谷子");
}
}
//小鸟正在吃谷子
public class Test {
public static void main(String[] args) {
Animal animal = findMyAnimal();
}
public static Animal findMyAnimal() {
Bird bird = new Bird("小鸟");
return bird;
}
}
3.3 动态绑定
当子类和父类中出现同名方法的时候, 再去调用会出现什么情况?
class Animal{
public int age;
public String name;
public void eat(){
System.out.println("eat()");
}
public Animal(String name,int age){
this.name=name;
this.age=age;
}
}
class Dog extends Animal{
public Dog(String name,int age) {
super(name,age);
}
public void eat(){
System.out.println("狼吞虎咽地eat()");
}
}
class Bird extends Animal{
public String wing;
public String name;
public void fly(){
System.out.println("fly()"+super.name+super.age);
}
public Bird(String name,int age,String wing) {
super(name, age);
this.wing = wing;
this.name=name;
this.age=age;
}
}
public class Test {
public static void main(String[] args) {
Animal animal=new Dog("haha",12);
animal.eat();
}
}
4.抽象类
在刚才的打印图形例子中, 我们发现, 父类 Shape 中的 draw 方法好像并没有什么实际工作, 主要的绘制图形都是由Shape 的各种子类的 draw 方法来完成的.
像这种没有实际工作的方法, 我们可以把它设计成一个抽象方法(abstractmethod), 包含抽象方法的类我们称为抽象类(abstract class)
abstract class Shape{
public abstract void draw();
}
注意事项: 1.在 draw 方法前加上 abstract 关键字, 表示这是一个抽象方法. 同时抽象方法没有方法体(没有 { }, 不能执行具体代码). 2.对于包含抽象方法的类, 必须加上 abstract 关键字表示这是一个抽象类. 3.抽象类不能被实例化 4.抽象类只能被继承 5.抽象类里面可以包含成员变量和成员方法 6.一个普通类继承了抽象类,需要重写抽象类的所有抽象方法 7.抽象类不能被final修饰,抽象方法也不能被final修饰 8.抽象类A继承了抽象类B,抽象类A可以不实现抽象类B的抽象方法 9.结合第8点,当一个普通类C继承了抽象类A,类C需要重写抽象类A和抽象类B全部的抽象方法 |
abstract class Shape{
public abstract void draw();
}
abstract class Shape{
public abstract void draw();
}
abstract class c extends Shape{
public abstract void eat();
}
class b extends c {
public void eat() {
System.out.println("eat()");
}
public void draw(){
System.out.println("draw()");
}
}
5.接口
接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含静态常量
interface IShape {
void draw();
}
class Cycle implements IShape {
@Override
public void draw() {
System.out.println("○");
}
}
public class Test {
public static void main(String[] args) {
IShape shape = new Rect();
shape.draw();
}
}
注意事项: 1.使用 interface 定义一个接口 2.接口中的方法默认是抽象方法, 因此可以省略 abstract 3.接口中的方法一定是 public, 因此可以省略 public 4.使用 implements 继承接口. 此时表达的含义不再是 "扩展", 而是 "实现" 5.接口中的成员变量,默认是public static final修饰的 6.接口是不能通过new关键字来实例化的 7.接口中可以用static方法,如果想要在接口中添加成员方法,可以使用default关键字 8.当一个类实现了一个接口,就必须重写接口里的所有抽象方法. 8.当一个类实现了一个接口,就必须重写接口里的所有抽象方法,重写抽象方式时,要在前面加上public,因为不添加默认是包修饰符,没有public的权限大. 9.接口和接口之间可以通过extends来进行拓展,如果一个接口B通过extends拓展另一个接口C的功能,使用普通类实现接口B的同时,也会有接口C拓展的功能. |
interface Itest {
public void draw();
}
public class TEST{
public static void drawf(Itest itest){
itest.draw();
}
public static void main(String[] args) {
drawf(new star());
drawf(new star());
drawf(new triangle());
}
}
6.Comparable接口实现
public class Student implements Comparable {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "[" + this.name + ":" + this.score + "]";
}
@Override
public int compareTo(Object o) {
Student s = (Student) o;
if (this.score > s.score) {
return -1;
} else if (this.score < s.score) {
return 1;
} else {
return 0;
}
}
}
public class TT {
public static void main(String[] args) {
Student[] students = new Student[] {
new Student("张三", 95),
new Student("李四", 96),
new Student("王五", 97),
new Student("赵六", 92),
};
System.out.println(students[0].compareTo(students[1])); //1
}
}