这篇文章将复习java中面向对象的特性
基本概念
面向对象 以类的方式组织代码 以对象形式的组织封装数据
面向对象三大特征 封装 继承 多态
先有对象后有类 对象是具体的事物 是对抽象概念的具体实例 类是抽象的 是对对象的抽象
对象
创建一个对象 有static关键字的是从属于类而非对象的静态方法
无static关键字的方法是需要类实例化之后才存在
public class Student {
//和类一起加载的
public static void sayHello(){
System.out.println("Hello");
}
//类实例化之后才存在
public void sayHi(){
System.out.println("hi");
}
}
分别调用这两个方法
//调用静态方法 类名.方法名
Student.sayHello();
//调用成员方法
Student student = new Student();
student.sayHi();
java中的值传递和引用传递 请看下面的两个方法
public static void change(Person p){
p.name = "abc";
}
public static void change(String s){
s = "abc";
}
调用这两个方法 第一种就是值传递 不会改变s的内容
第二种引用传递 传递的是对象的引用(指针)会改变内容
String s = "aaa";
change(s);
System.out.println(s); //aaa
Person p1 = new Person();
change(p1); //引用传递
System.out.println(p1.name); //abc
构造方法
构造器(构造方法) 创建对象的时候会调用
如果不写也会存在构造方法(默认无参构造器)
写了有参构造器 无参构造器就没了 不过通常要写无参构造器
构造方法名字必须和类名相同 且没有返回值
其作用是实例化一些对象
idea中alt+insert可以自动生成构造器
this关键字就是代指这个类 谁调用这个类 this就是谁
程序要追求高内聚 低耦合
public class Student {
String name;
int age;
public Student(){
}
public Student(String name , int age){
this.name = name;
this.age = age;
}
public void study(){
System.out.println(this.name + " is study");
}
}
在main方法中测试
Student student = new Student();
student.name = "Jack";
student.study();
Student student2 = new Student("Bob", 24);
System.out.println(student2.name + " " + student2.age);
封装
通俗点说 就是把数据封装起来 对外提供一个接口
提高程序的安全性 隐藏代码细节 统一了接口 提高了系统的可维护性
简单来说 属性私有 提供set get
请看下面的代码 private关键字 使得属性和方法只能在本类中调用 别的类中访问不到
class Student{
//属性私有 get set
private String name;
private int age;
//提供public get set 方法
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
}
调用setter和getter方法
public static void main(String[] args) {
Student student = new Student();
student.setName("Jerry");
System.out.println(student.getName());
}
继承
继承的本质是对类的抽象 实现对现实世界更好的建模
子类继承父类 就会拥有父类的全部不私有的方法和属性
而使用private关键字的属性和方法不会被继承
通过final修饰的类不能被继承
适用范围 public protected default private
在java中所有的类都继承object类
java中只能单继承 一个子类只能有一个父类
请看下面的代码 子类中没有say()方法 但是继承(extends关键字)后可以调用父类的方法
public class Test01 {
public static void main(String[] args) {
Student student = new Student();
student.say(); //hello
}
}
class Person{
public void say(){
System.out.println("hello");
}
}
class Student extends Person{
//子类是父类的拓展
}
用super关键字可以访问父类的属性和方法
public class Test01 {
public static void main(String[] args) {
Student student = new Student();
student.test(); // Teemo Teemo jack
student.test2(); //test hello
}
}
class Person{
protected String name = "jack";
public void say(){
System.out.println("hello");
}
}
class Student extends Person{
//子类是父类的拓展
private String name = "Teemo";
public void test(){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
public void say(){
System.out.println("test");
}
public void test2(){
say();
super.say();
}
}
子类继承父类之后 创建对象的时候会默认调用父类的无参构造器
原因是子类无参构造第一样隐藏了一个super();这个方法会调用父类的无参构造
这句话只能放在第一行 也可以super(xxx);里面放上参数(父类的有参构造器)
当然可以用this();代替(调用子类的无参构造)当然也只能放在构造器的第一行
public Student(){
super("jack");
}
关于方法重写 当在子类写出一个方法方法名 返回值 形参类型一致时 (修饰符范围可以扩大 抛出的异常可以被缩小但不能被扩大) (对final修饰的不能重写)子类调用这个方法 会优先调用子类的这个写出来的方法 请看下面的代码
public class Test01 {
public static void main(String[] args) {
B b = new B();//方法重写
b.test1(); //B test1
}
}
class A{
public void test1(){
System.out.println("A test1");
}
}
class B extends A{
public void test1(){
System.out.println("B test1");
}
}
多态
多态可以使我们能够动态编译 可拓展性更强 能让程序变的更灵活
多态是方法的多态 属性没有多态
父类和子类必须有关系
个人理解 s2调用方法的时候 现在父类里面找到那个方法 找不到就不能调用(比如test2()方法)找到之后检查子类是否重写了 如果重写了就调用重写之后的方法
s1则是直接在子类中找这个方法 找不到再去父类中找 也是调用的重写之后的
public class Test01 {
public static void main(String[] args) {
Student s1 = new Student();
//父类的引用指向子类
Person s2 = new Student();
Object s3 = new Student();
//子类重写了父类的方法 就调用子类的
s2.test1(); //Student test2
//没有重写就调用父类的方法
s2.test3(); //Person test3
}
}
class Person{
public void test1(){
System.out.println("Person test1");
}
public void test3(){
System.out.println("Person test3");
}
}
class Student extends Person{
public void test1(){
System.out.println("Student test2");
}
public void test2(){
System.out.println("Student test2 ");
}
}
请看下面的代码 父类型引用指向子类型对象 上来寻找的是左边的那个类
public class Test01 {
public static void main(String[] args) {
A a = new B();
B b = new B();//方法重写
a.test1(); //B test1
b.test1(); //B test1
//static方法从属于类
a.test2(); //static A
b.test2(); //static B
}
}
class A{
public void test1(){
System.out.println("A test1");
}
public static void test2(){
System.out.println("static A");
}
}
class B extends A{
public void test1(){
System.out.println("B test1");
}
public static void test2(){
System.out.println("static B");
}
}
关于instanceof关键字
能否编译通过就是创建对象所在的类与instanceof后面的是否有继承关系
而true和false是由对象右边的具体实例与instanceof后面能否互相转化
public class Test01 {
public static void main(String[] args) {
//能否编译通过就是创建对象所在的类与instanceof后面的是否有继承关系
//而true和false是由对象右边的具体实例与instanceof后面能否互相转化
Person s1 = new Student();
System.out.println(s1 instanceof Student); //true
System.out.println(s1 instanceof Person); //true
System.out.println(s1 instanceof Teacher); //false
Student s2 = new Student();
System.out.println(s2 instanceof Student); //true
System.out.println(s2 instanceof Person); //true
((Student)s1).go(); //强制类型转化
}
}
class Person{
}
class Student extends Person{
public void go(){
System.out.println("go");
}
}
class Teacher extends Person{
}
static关键字 记住在方法区存在 且从属于类 请看下面的代码
public class Test02 {
static int i = 0;
{
//代码块(匿名代码块)
System.out.println("匿名代码块");
}
static {
//静态代码块
//类加载的时候执行 只执行一次
System.out.println("静态代码块");
}
public Test02(){
System.out.println("构造器");
}
public static void main(String[] args) {
Test02 t = new Test02();
/*
静态代码块
匿名代码块
构造器
*/
test();
test();
System.out.println(i); //2
}
public static void test(){
i++;
}
}
抽象类
抽象类用abstract修饰
抽象方法只有方法的名字 没有方法的实现
抽象类可以有普通的方法
类中有抽象方法必须是抽象类
继承抽象类必须要实现它其中所有的抽象方法 除非自己本身是抽象的
public abstract class Action {
public abstract void doSome();
}
class A extends Action{
@Override
public void doSome() {
System.out.println("doSome");
}
}
接口
接口就是规范 定义的是一组规则
接口中的方法都是抽象的 public abstract
类可以利用接口实现多继承(伪多继承)
实现类必须实现接口定义的所有方法
请看代码
public interface UserService {
void add(String name);
int query(int num);
}
public class UserServiceImpl implements UserService {
@Override
public void add(String name) {
System.out.println("add");
}
@Override
public int query(int num) {
System.out.println("query");
return -1;
}
}
内部类
public class Outer {
private int id;
public void out(){
System.out.println("out");
}
class Inner{
//可以获得外部类私有属性 私有方法
public void in(){
id = 10;
System.out.println(id);
System.out.println("in");
}
}
}
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.in(); // 10 in
}
加入static关键字就变成静态内部类 由于程序开始时静态内部类就创建了 故访问不到id
匿名内部类 没有名字的类
public class Test02{
public static void main(String[] args) {
UserService user = new UserService() {
public void hello() {
System.out.println("Hello");
}
};
}
}
interface UserService{
void hello();
}