面向对象的核心概念对象

  类:对一类事物描述,是抽象的、概念上的定义。

  对象:实际存在的该类事物的每个个体,因而也成为实例(Instance)。

Java类及类的成员属性(成员变量Field)和方法(method)

类对象的内存结构

Animal a1 = new Animal();
a1.name = "花花";
a1.age = 3;

之前梳理数组的时候说过,栈中的对象存放对象的引用及Animal a1的a1这个引用。堆空间都是new出的东西包括成员变量。

  ① 在栈中声明一个a1的引用变量

  ② 在堆中申请一块区域存储new Animal并为成员变量赋默认值(name=null,age=0)。

  ③ a1的引用变量指向堆的new Animal的首地址(16进制数字)。

  ④ a1.name="花花":修改成员变量name值为花花。

  ⑤ a1.age = 3:修改成员变量age值为3。

Animal a2 = new Animal();

每次new出来的对象都是在堆中重新申请的一个新空间

Animal a3 = a1;
a3.name = "草草"

① 在栈中声明一个a3的引用变量

② a3的引用变量指向a1的指向的堆空间的首地址

③ a3.name = "草草":修改成员变量name值为"草草"。

最终,a1和a3的成员变量name都修改成了草草。

类的== 和equals

 == 表示对象引用的地址是否相等,即16位的首地址码是否一致。

类没有重写equals,所以用的是Object的equals的方法,看源码就能看出来,和==一样。

想让比较的两个类所有属性值都一样的情况下就相等的话,需要自己重写equals方法。

类的成员之一:属性

成员变量(属性)和局部变量

1、修饰符

  ① 成员变量:public、private、protected、default、final、static

  ② 局部变量:final

  笔试题:

  public class aClass {
    void run() {
      static int i = 0;
      i++;
      System.out.println(i);
    }
    public static void main(String args[]) {
      aClass obj = new aClass();
      obj.run();
      obj.run();
    }
  }

结果为:A:0    B:1    C:2    D:编译错误

很明显是选D,因为局部变量只能用修饰符final修饰。

2、默认初始化值:

  ① 局部变量:类的局部变量和数组元素的默认初始化值一致的。

  ② 成员变量:没有默认值。

3、内存中存放的位置:

  ① 局部变量:堆

  ② 成员变量:栈

  ① 在栈中声明一个p1的引用变量

  ② 在堆中申请一块区域存储new Person并为成员变量赋默认值(name=null,age=0,sex=false)。

  ③ p1的引用变量指向堆的new Person的首地址(16进制数字)。

  ④ 在栈中申请n的变量并赋值为付昊(n为形参的参数名字)

  ⑤ 将n这个局部变量的值赋值给刚才new Person的成员变量name

  ⑥ setName执行完毕后,n这个局部变量销毁。

4、类对象的属性赋值顺序:

  ① 属性的默认值:private int age;

  ② 属性的显式赋值:private int age = 1;

  ③ 构造器给属性赋值:public Person(int a){age = a;}

  ④ 通过setter方法赋值:public void setAge(int n){age = n;}

 类的成员之二:方法

1、修饰符:private、protect、public、static、final、synchronize。

2、重载:方法名字相同,参数列表不同(参数个数不同和类型不同)。

3、重写:继承中子类重新实现了父类的方法。

  ① 要求子类方法名字和参数列表完全和父类一样。

  ② 子类方法的修饰符不能小于父类方法的修饰符。

4、形参:

java中的参数传递机制:值传递

  ① 基本数据类型传递(传递的值是具体的实参的基本数据类型的值)

public class TestArgsTransfer {
public void swap(int i,int j){
int temp = i;
i = j;
j = temp;
}
public static void main(String[] args){
TestArgsTransfer tt = new TestArgsTransfer();
int i = 10;
int j = 5;
tt.swap(i,j);
}
}

内存结构

  ② 引用数据类型传递(传递的值是引用对象的16位的首地址值)

public class TestArgsTransfer {
public void swap(DataSwap d){
int temp = d.i;
d.i = d.j;
d.j = temp;
}
public static void main(String[] args){
TestArgsTransfer tt = new TestArgsTransfer();
DataSwap ds = new DataSwap();
tt.swap(ds);
}
}
class DataSwap{
int i = 10;
int j = 5;
}

类的成员之三:构造器:

特点:

  ① 和类名字一致

  ② 没有返回值

  ③ 只能被4个访问权限修饰符修饰

作用:

  ① 创建对象

  ② 给创建的对象的属性赋值,通过构造器的形参实现。

【知识点】:

  ① 若不显式的声明类的构造器的话,程序会默认的提供一个空参的构造器。

  ② 若显式的声明的类的构造器的话,那么默认的构造器就不再提供。

  ③ 类的多个构造器之间形成重载。

java封装性:

1、将属性私有化,然后通过调用getter和setter方法来获取或者设置属性。

  为什么不直接使用对象.属性直接使用属性呢?

  设想,你有一个Person类代表一个人,Person有一个char类型的sex字段表示性别,理论上,sex只接受两个值, 'M '和 'F ',但如果你把sex字段设为public,

  你很难限制你的用户只给它赋 'M '或 'F '值。将sex设为private,再用setSex()来设置性别,你就完全可以控制这种行为了。而且你还可以控制只能get不能set,

  或相反,但如果是public就不行了。另外我们可能并不想对属性进行写操作,这个时候,可以直接不写set方法。这就是只读属性了。

2、通过4种访问权限修饰符隐藏了类或者方法

java继承性:extends

1、子类继承父类后,父类中声明的属性、方法,子类就可以获取到。

2、子类除了通过继承,获取父类的结构之外,还可以定义自己特有的成分。

3、java中的类只支持单继承,不支持多继承。

4、由于Object是所有类的超类,那么你在最顶层的父类其实还会调用Object的无参构造函数。

子类对象实例化的全过程

 public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setAge(10);
dog.setName("花花");
dog.setHostName("小明");
System.out.println("age:" + dog.getAge() + "\nname:" + dog.getName() + "\nhostname:" + dog.getHostName());
}
}
//生物
class Creator{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//动物
class Animal extends Creator{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//狗
class Dog extends Animal{
private String hostName;
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
}

子类对象的实例化并没有在堆中创建了任何它的父类对象,只是把父类对象的属性带了过来。

 java多态性

多态性:可以理解为一个事物的多种表现形态。

1、方法的重载与重写
  同一类中方法名相同,但是调用子类和父类的表现却是不同的。

2、子类对象的多态性

Person p = new Student(); //子类对象的多态性,父类的引用指向子类对象
//虚拟方法调用:实际调用子类重写父类的方法,但是父类必须有此方法声明
p.eat();
p.walk();

3、向下转型和向上转型

Person p = new Student();//向上转型
Student s = (Student)p;//向下转型,强制类型转换

  但是这种转型是有一些风险的,那么最好用instanceof来判断

4、子类对象的多态性,并不适用属性。加入父类和子类的属性值相同,左边是谁,就使用谁的属性。

匿名类对象:

1、创建类的对象是没有名字的。

2、使用场景:当我们只需要调用一次类的对象时。

3、特点:创建的对象调用完一次这个对象就销毁了。

new Person().getName;

关键字:

1、this

this表示当前对象,用来修饰属性、方法、构造器

在构造器内部,this必须声明在首行。

class Cake{
private String name;
public Cake(){
System.out.println("cake");
}
public Cake(String name){
this();//this调用无参的构造器
this.name = name;//this调用当前对象
}
}

2、super

this表示父类对象,用来修饰属性、方法、构造器

在构造器内部,supper必须声明在首行。

在构造器内部,子类构造器都默认第一步调用父类无参的构造器,除非你加了this,因为只要加了this的话super就不起作用了。

 class Person{
public Person(){
System.out.println("p1");
}
public Person(int id,String name){
this();
System.out.println("p2");
}
}
class Student extends Person{
public Student(){
System.out.println("s1");
}
public Student(String n){
System.out.println("s2");
}
public Student(int g){
this("s");
System.out.println("s3");
}
}
public class Main {
public static void main(String[] args){
Student student = new Student(0);
}
}

输出结果:p1 s1 s2

总结:

  ① 在构造器内要么用this要么用super,用了this,super就会失效。

  ② 在构造器内如果子类不显式的调用父类的构造器,那么默认调用无参的super();

  ③ 设计父类的时候,如果不显式的声明一个无参的构造函数,那么有可能造成程序编译错误。

3、static

静态的,可以修饰属性、方法、代码块、内部类

1)属性(类变量):

class SportsMan {
String name;
int age;
static String nation;
public SportsMan(String name, int age) {
super();
this.name = name;
this.age = age;
}
}

  

总结:

  ① SportsMan类中的nation属性是static修饰的,由这个类创建的对象都共用这个属性。

  ② 类变量的加载早于对象,所以既可以用“sp1.nation”,也可以用“SportsMan.nation”调。

  ③ 当其中一个对象对此类变量进行修改,会影响其他对象的类变量的一个调用。

    

2)方法:

  ① 随着类的加载而加载,在内存中也是独一份。

  ② 可以直接通过“类.类方法”

  ③ 静态方法内部可以调用静态的属性或者方法,但是不能调用非静态的属性和方法,因为静态的生命周期要早于非静态对象。

  ④ 非静态的方法可以调用静态的属性和方法,因为非静态的方法晚于静态的方法和属性。

4、final

  ① 修饰类 :不能被继承

  ② 修饰方法:不能被重写

  ③ 修饰属性:此属性就是一个常量。此常量不能使用默认初始化(除非在构造器中或者非静态代码块初始化),可以显式的赋值。

     final int I;// 编译错误
final int I = 12;//正确
public void m(){
I = 15; // 编译错误
}

  但是如果放在构造器中,就没问题。

     final int I;//正确
public A(){
I = 15;//正确
System.out.println("3");
}

笔试题一:

 public class Something{
  public int addOne(final int x){
    return ++x;
  }
}

  肯定编译错误,final一旦修饰的时候赋了值,那么对不起,我的值就是最终的值,以后谁都不能改,谁改谁错。

笔试题二:

 public class Something{
  public static void main(String[] args){
    Other o = new Other();
    new Something.addOne(o);
  }
  public void addOne(final Ohter o){
    o.i++
  }
}
class Other{
  public int i;
}

  肯定不出错,final修饰的是o(即o的堆地址),o里的属性没关系,想怎么变就怎么变。

类的成员之四:初始化块

1)非静态块

 class Person{
int id = 0;
String name = "n";
{
id = 10;
name = "ni";
System.out.println("你好:你");
}
{
id = 11;
name = "hao";
System.out.println("你好:好");
}
public Person(){
id = 12;
name = "ni hao";
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
System.out.println(p1.id + "\n" + p1.name);
}
}

输出结果:

  你好:你
  你好:好
  12
  ni hao

① 可有对类的属性(静态和非静态)进行初始化操作

② 里面可以有输出语句

③ 属性赋值的顺序:默认初始化值--->显式初始化或者代码块初始化(此处看顺序位置)--->构造器--->通过setter方法

2)静态块

① 随着类的加载而加载,而且只被加载一次。

② 静态的代码块在非静态代码块之前运行

③ 非静态的属性不能放在静态代码块

笔试题:

 class A{
static {
System.out.println("1");
}
{
System.out.println("2");
}
public A(){
System.out.println("3");
}
}
class B extends A{
static {
System.out.println("a");
}
{
System.out.println("b");
}
public B(){
System.out.println("c");
}
}
public class Main {
public static void main(String[] args) {
A a = new B();
a = new A();
}
}

输出结果:1 a 2 3

总结:

  ① 不管是静态代码块还是非静态代码块都是从父类开始执行的。

  ② 静态代码块只执行一次,非静态代码块new一次执行一次。

抽象类:

1、抽象类

  ① 抽象类不能被实例化

  ② 抽象类可以有构造函数

  ③ 抽象方法所在的类一定是抽象类

  ④ 抽象类中可以没有抽象方法

  ⑤ 不能和final共同修饰类

2、抽象方法

  ① 抽象方法必须需要子类进行重写

  ② 抽象类中可以有具体的实现方法。

  ③ 若子类是一个具体的“实体类”,那么就必须实现继承抽象类中的所有的抽象方法

  ④ 若子类继承抽象类,没有重写完所有的抽象方法,那么此类必须也是一个抽象类

3、其他:abstract不能修饰属性、构造器、private、final、static

  ① abstract 不能修饰属性,因为子类的属性是无法重写父类属性的

  ② abstract 不能修饰构造器,因为构造器不能被重写

  ③ abctract 不能和private修饰,因为你本来就是想让子类进行重写的,private的话你还让子类怎么重写。

  ④ final就不用说了,它修饰的方法不能被重写。它两个本身就是矛盾的。

  ⑤ static的话,直接用类.方法调用时不合规的。

 abstract class Animal {
public Animal(){
// 只要实例化子类,抽象类的构造器会被执行。
System.out.println("我是一个抽象动物");
}
public void breath(){
//抽象类中可以有具体实现方法。可以通过实例化子类,再调用抽象类的方法。
System.out.println("动物都会呼吸");
}
public abstract void cry();
} class Cat extends Animal{ @Override
public void cry() {
System.out.println("猫叫:喵喵...");
}
} class Dog extends Animal{ @Override
public void cry() {
System.out.println("狗叫:汪汪...");
} }
public class Main {
public static void main(String[] args) {
Animal cat = new Cat();
cat.cry();
}
}

执行结果:

  我是一个抽象动物
  猫叫:喵喵...

 接口

 接口是一个特殊的抽象类,只有两个元素①常量 ②抽象方法

 1、接口不需要写权限修饰符,肯定是public。

2、常量默认使用public static final修饰,方法默认使用public abstract修饰

 3、接口既不能实例化,也不能有构造器

 4、如果实现接口,那么就需要实现接口的所有抽象方法

 5、接口之间可以多继承

 6、类可以实现多个接口,但是需要实现这些接口所有的抽象方法。

 public class DayStudy {
public static void main(String[] args) {
//1、第一个多态性。格式:接口 参数 = new 实现类()
Runner d = new Duck();
test1(d);
//2、第二个多态性。参数用接口类型,传入实现类,解耦
Duck d1 = new Duck();
test1(d1);
test2(d1);
test3(d1);
}
public static void test1(Runner r ){
r.run();
}
public static void test2(Swiner s ) {
s.swin();
}
public static void test3(Flier f ) {
f.fly();
}
}
interface Runner{
void run();
}
interface Swiner{
void swin();
}
interface Flier{
void fly();
}
class Duck implements Runner,Swiner,Flier{
@Override
public void run() {
System.out.println("会跑");
}
@Override
public void swin() {
System.out.println("会下水游泳");
}
@Override
public void fly() {
System.out.println("会飞");
}
}
接口匿名类 :接口 参数 = new 接口(){ 这里面具体把接口的抽象类实现 }
Runner r = new Runner(){
  @override
  public void run(){
    system.out.printLn("匿名类");
  }
}

跟着刚哥梳理java知识点——面向对象(八)的更多相关文章

  1. 跟着刚哥梳理java知识点——多线程(十六)

    创建多线程第一种方式:① 继承:继承Thread.② 重写:重写Thread类的run()方法③ 创建:创建一个子类的对象④ 调用:调用线程的start()方法,启动此线程,调用run()方法 cla ...

  2. 跟着刚哥梳理java知识点——深入理解String类(九)

    一.String类 想要了解一个类,最好的办法就是看这个类的实现源代码,来看一下String类的源码: public final class String implements java.io.Ser ...

  3. 跟着刚哥梳理java知识点——变量之间的类型转换(四)

    变量之间的类型转换主要包括自动类型转换和强制类型转换. 1.自动类型转换:当容量小的数据类型与容量大的数据类型做运算时,容量小的会自动的转换成容量大的类型. [知识点]: a)char,byte,sh ...

  4. 跟着刚哥梳理java知识点——注释(二)

    1.单行注释 // //这是main方法,程序的入口 public static void main(String[] args) { //输出语句 System.out.println(" ...

  5. 跟着刚哥梳理java知识点——HelloWorld和常见问题(一)

    1.按照国际惯例,写一段输出HelloWorld的java语句: public class HelloWorld { //这是main方法,程序的主入口 public static void main ...

  6. 跟着刚哥梳理java知识点——IO(十五)

    凡是与输入.输出相关的类.接口都定义在java.io包下 java.io.File类 1.File是一个类,可以有构造器创建其对象.此对象对应着一个文件或者一个目录. 2.File中的类,仅涉及到如何 ...

  7. 跟着刚哥梳理java知识点——枚举和注解(十四)

    enum Season{ SPRING("spring","春暖花开"), SUMMER("summer","夏日炎炎" ...

  8. 跟着刚哥梳理java知识点——泛型(十三)

    一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: public class GenericTest { public static void main(String[] a ...

  9. 跟着刚哥梳理java知识点——集合(十二)

    Java集合分为Collection和Map两种体系 一.Collection接口: Collections接口为我们提供了以下方法: size():返回集合中元素的个数 add(Object obj ...

随机推荐

  1. 《Shell脚本学习指南》学习笔记之自定义函数

    Shell的函数在使用之前必须先定义,定义格式: [ function ] funname [()] { action; [return int;] } 可以带function fun()定义,也可以 ...

  2. HTM5新手学习的一些日常总结,相互交流和相互学习。

    第一天 一.HTML--网页的源码(超文本标签语言) HTML标签 标签式是HTML最基本单位和最重要的组成. 使<和>扩起来 标签都是闭合的(规范) HTML标签属性 是标签的一部分,用 ...

  3. .NET 发布网站步骤

    本文章分为三个部分: web网站发布.IIS6 安装方法.ASP.NET v4.0 安装方法 一.web网站发布 1.打开 Visual Studio 2013 编译环境 2.在其解决方案上右击弹出重 ...

  4. java Thread和Runable的深刻理解

    线程(Thread)是指程序的运行流程,多线程机制指同时运行多个程序块. Java中实现多线程有两种方法:继承Thread类:实现Runnable接口. Thread类的run()方法的制定者:接口R ...

  5. 右键打开cmd命令出错

    今天想在E盘git clone一个工程项目下来,发现自己的window10上,出现了如下问题(不知道是不是是什么软件引起的冲突) 在度娘里面找了半天也没有解决问题,只有通过如下方法实现了 ctrl+r ...

  6. loadrunner:判断是否服务器连接池瓶颈

    分析Web Resources中的Connections per second可以判断是否服务器连接池瓶颈. connections per second会给出两种不同状态的连接数:中断的连接和新建的 ...

  7. NOI全国赛(2001)--食物链

    今天写了道并查集的题,看来并查集的题刷少了,,,,,用法好神奇啊!!!开三倍并查集 用i表示自己,i+n存天敌,i+2*n存可以克制de,再逻辑判断一下即可. 所以,要意识到并查集的分类处理可以开不同 ...

  8. iOS开发优秀博客和软件推荐

    iOSBlogAndTools iOS开发优秀博客和软件推荐 本博客和工具列表由广大iOS开发者收集和推荐,如果大家有好的博客或者工具想要分享请点击:我要提交. 收到大家的提交后会及时收录与更新.Gi ...

  9. webstorm入手笔记

    一.webstorm学习前小记 webstorm是一款现在前端用的比较多的IDE,其优势也比较多,这个大家在网上随便搜搜就可以找到了.但是本人大部分的时间都是使用sublime text工作,最近由于 ...

  10. vmware克隆之后网卡起不来的问题

    问题: 克隆一台主机之后,改主机的网卡起不来,只有一个本地的回环地址网卡. 使用如下的命令都无效. /etc/init.d/network restart ifup eth0 原因: 这一vmware ...