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