java面向对象编程

Java面向对象编程

1. 构造方法

public class Person {

	private String name;
	private int age;

  // 构造方法1
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
  // 构造方法2
  public Person(String name) {
    this.name = name;
  }

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name.trim();
	}

	public int getAge() {
		return this.age;
	}
}

2. 方法重载

方法重载(overload)是指:

  • 多个方法的方法名相同
  • 单各个的参数不同
    • 参数个数不同
    • 参数类型不同
    • 参数位置不同
  • 方法返回值类型通常都是相同的
public class Hello() {
  public void hello(String) {}
  public void hello(int age) {}
  public void hello(String name, int age) {}
  public void hello(int age, String name) {}
}

3. 继承

3.1 继承的格式

  • java 只允许class继承自一个类
  • 一个类有且仅有一个父类(Object除外)
public class Person {
  private String name;
  protected int age;
}
public class Student extends Person {}

3.2 protected关键字

  • Person类定义的private字段无法被子类访问
  • 用protected修饰符的字段可以被子类访问
  • Protected把字段和方法的访问权限控制在继承内部

3.3 super关键字

  • super关键字标识父类(超类)
  • 构造方法的第一行语句必须调用super()
  • 没有super的编译器会子弟共生成super()
public class Person {
  public Person(String name) {
    System.out.println("create Person: " + name);
  }
}

public class Student extends Person {
  public Student(String name) {
    super(name);
    System.out.println("create Student: " + name);
  }
}

3.4 instanceof操作符

判断实例p是否属于Person类

System.out.println(p instanceof Person);   //true

4. 多态(Polymorphic)

4.1 @override

  • 子类覆写父类的方法使用注解(@Override)
  • @Override不是必须的
  • 在子类中加上@Override可以让编译器帮助检查是否进行了正确的覆写

4.2 多态

  • 多态是指对某个类型的方法调用, 其真正执行的方法取决于运行是实际类型的方法
  • 对某个类型调用某个方法, 执行的方法可能是某个子类的覆写方法
  • 利用多态, 允许添加更多类型的子类实现功能扩展

4.3 final关键字

  • 用final修饰的方法不能被Override
  • 用final修饰的类不能被继承
  • 用final修饰的字段在初始化后不能被修改

5. 抽象类

如果一个class定义了方法, 但没有具体执行代码, 这个方法就是抽象方法

  • 一个抽象方法用abstract修饰
  • 抽象方法没有任何执行语句
  • 因为无法执行抽象方法, 因此这个类必须申明为抽象类(abstract class), 所以定义了抽象方法的类就是抽象类
  • 无法实例化一个抽象类

无法实例化的抽象类有什么作用?

  • 抽象类用于被继承
  • 抽象类可以强迫子类实现其定义的抽象方法(否则编译错误)
  • 抽象方法实际上相当于定义了一个"规范"

注意: 从抽象类继承的子类必须实现抽象方法, 如果不实现抽象方法, 则该类仍然是一个抽象类

// 父类
public abstract class Person {
    public abstract void run();
    public void hello() {
        System.out.println("hello world");
    }
}
// 子类
public class Student extends Person{
    public Student(String name) {
        super();
        System.out.println("create Student: " + name);
    }
    
    @Override
    public void run() {
        System.out.println("Student running");
    }


    public static void main(String[] args) {
        Student student = new Student("lingjing");
        student.run();
        student.hello();
    }
}

6. 接口

如果一个抽象类没有字段, 所有方法都是抽象方法, 就可以把该抽象类改成成接口(interface)

  • 使用interface声明一个接口
  • 接口定义的方法默认都public abstract(不需要写)
  • 一个interface可以继承另外一个interface, 继承使用extends, 相当于扩展了接口的方法

抽象类和接口对比:

abstract class Interface
继承 只能extends一个class 可以implements多个interface
字段 可以定义实例字段 不能定义实例字段
抽象方法 可以定义抽象方法 可以定义抽象方法
非抽象方法 可以定义非抽象方法 可以定义default方法

7. 静态字段和方法

7.1静态字段

static 修饰字段就是静态字段

  • 所有实例共享一个静态字段
  • 不推荐使用实例变量访问静态字段: Person person = new Person(); person.number
  • 推荐使用类名访问静态字段: Person.number
  • 可以把静态字段理解成描述class本身的字段
public class Person {
  public static int number = 100;
}

7.2 静态方法

用static修饰的方法称为静态方法

  • 一搬调用实例的方法必须通过实例变量: Person person = new Person(); person.run()
  • 调用静态方法不需要实例变量, 提前是必须是静态方法: Person.run()
  • 静态方法不能访问this变量
  • 静态方法不能访问实例字段
  • 静态方法可以访问静态字段
  • 静态方法经常用于工具类
    • Arrays.sort()
    • Math.random()

8.访问权限

  • public
    • 定义为public的field, method可以被其他类访问
  • Private
    • 定义为private的的class无法被其他类访问
    • 访问private class被限定在外层class的内部
    • 定义一个class内部的class称为内部类
  • protected
    • protected作用于继承关系
    • 定义为protected的字段和方法可以被子类访问
  • package
    • 包作用域是指一个类允许访问同一个package的没有public, private修饰的class, 没有public, protected, private修饰的字段和方法

9. classpath和jar

9.1 classpath

classpath是一个环境变量, 指示JVM在启动程序的时候在什么路径下去搜索相关的类

例如:

java -classpath /usr/bin;/data/servers/hadoop/bin com.longfor.Hello
#或者
java -cp /usr/bin;/data/servers/hadoop/bin com.longfor.Hello

这样JVM在加载com.longfor.Hello这个类的时候, 一次查找

  • <当前目录>/com/longfor/Hello.class
  • /usr/bin/com/longfor/Hello.class
  • /data/servers/hadoop/bin/com/longfor/Hello.class

在某个路劲在找到, 就不在继续搜索, 如果没有找到, 就会报错

classpath的设定方法:

推荐使用:

java -classpath /usr/bin;/data/servers/hadoop/bin com.longfor.Hello
#或者
java -cp /usr/bin;/data/servers/hadoop/bin com.longfor.Hello

如果没有设置环境变量, 也没有设置-cp参数, 默认的classpath为. 及当前目录

9.2 jar包

  • jar包是zip格式的压缩文件, 包含若干.class文件

  • jar包相当于目录

  • classpath可以包含jar文件: /data/tmp/all.jar

  • 使用jar可以避免大量的目录和.class文件

jar的其他动能

  • jar包课包含一个特殊的/META-INF/MANIFEST.MF文件
  • MANIFEST.MF是纯文本, 可以指定Main-Class和其他信息
  • jar包可以包含其他jar包

jdk的class

  • jvm运行会自动加载jdk自带的class
  • jdk自带的class被打包在rt.jar中
  • 不需要在classpath中引用rt.jar

示例:

jt0101020164:hadooptest lingjing$ tree META-INF/
META-INF/
└── MANIFEST.MF
jt0101020164:hadooptest lingjing$ cat META-INF/MANIFEST.MF 
Manifest-Version: 1.0
Main-Class: com.longfor.Main
X-Copyright: blablabla...
X-Build-Version: 1.0

10. StringBuilder

  • StringBuilder必须通过toString()转换成字符串才可以当成字符串使用
  • StringBuilder是可变对象, 用来高效拼接字符创
  • StringBuffer是StringBuilder的线程安全版本, 很少用
  • StringBuilder可以支持链式操作, 实现链式操作的关键是返回实例本身
StringBuilder sb = new StringBuilder(1024);
String s = sb.append("ajing")
  .append(name)
  .append("!")
  .insert(0, "hello, ")
  .toString();
String s1 = "hello " + name + "!";
  • 编译器在内部自动把多个连续的 + 操作优化为StringBuilder操作

11. 包装类型

int <———>Integer

public class Integer {
  private int value;
  public Integer(int value) {
    this.value = value;
  }
}

定义一个Integer类, 包含一个实例字段int, 可以把Integer视为int的包装类型

JDK为各种基本类型都创建了对应的包装类型

基本类型 对应的引用类型
boolean Boolean
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character

编译器可以自动在int和Integer直接转型

  • 自动装箱: auto boxing int -> Integer
  • 自动拆箱: auto unboxing Integer ->int
Integer n = 99;
int i = n;
Integer s = i + n;
// Integer s = Integer.valueof(i + n.intValue());
  • 自动装箱和自动拆箱值发生在编译阶段
  • 装箱和拆箱会影响执行效率
  • 编译后的class代码是严格区分基本类型和引用类型的

包装类型定义了一些有用的静态变量

Boolean.TRUE
Boolean.FALSE
Integer.MAX_VALUE; //2147483647
Integer.MIN_VALUE; //-2147483648
posted @ 2019-06-04 22:44  阿晶  阅读(328)  评论(0编辑  收藏  举报