java随笔三,真正的class大总结

java随笔三:class

一.对象与对象引用

class A{}

A pa = new A();

差不多就是A *pa = new A();显然new的是对象,pa是引用(Java毙了指针,把他换个名字叫引用)。

二.对象作为参数传递的特点

#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#define ll long long
using namespace std;
class A
{
public:
    int a;
};
A *build()
{
    A *b = new A();
    b->a = 1;
    return b;
}
int main()
{
    A *c = build();
    cout<<c->a<<endl;
}
class A
{
    int a;
}
public class test
{
    public static A build()
    {
        A b = new A();
        b.a = 1;
        return b;
    }
    public static void main(String[] args)
    { 
        A c = build();
        System.out.println(c.a);
    }
}

不能说十分相像,只能说基本一样2333。

(据说气势磅礴的头文件能使编程水平上升)

三.对象初始化顺序

3.1.默认初始化

3.2.定义初始化

3.3.构造初始化

四.static

有什么可说的呢。

这跟c++基本上一毛一样。

还有说实话那个什么static代码块和直接在外面写有什么区别吗?

#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#define ll long long
#define LoveLivesuperstar  cout<<"药药,切克闹,唐可可我最闪耀!!!"<<endl;
using namespace std;
class A
{
public:
    int a;
    static int b;
    A()
    {
        a = 0;
        b++;
    }
    /*static{
        cout<<"药药,切克闹,唐可可我最闪耀!!!"<<endl;
    }*/
    //c++只能通过宏定义来实现
    static void call()
    {
        cout<<"\t\tTerrorist win!"<<endl;
        cout<<"ez4ence,ence,ence,dens,"
        <<"puttted upperbelt,"
        <<"puttted upperbelt!!!"<<endl;
    }
};
int A::b = 0;
int main()
{
    LoveLivesuperstar
    A a1,a2;
    cout<<a1.b<<endl;
    a1.call();
}

​
class A
{
    int a;
    static int b;
    public A()
    {
        b++;
    }
    static{
        System.out.print("煎饼果子来一套,坚持练习不迟到!");
        System.out.println("动次打次~动次打次~动次打次~动次打次~!");
    }
    static void call()
    {
        System.out.println("\t\t Terrorist win!");
        System.out.println("are you mad er?             why you mad bruh ?");
    }
}
public class test
{

    public static void main(String[] args)
    { 
        A a1 = new A(),a2 = new A();
        System.out.println(A.b);
        A.call();
    }
}

五.final

1.在成员上相当于const;

2.在方法上不相当于const;const在c++不能阻止复写与重载的发生。但是c++虚函数可以用override和final阻止复写。c++11及其之后的c++满足这样的需求。

c++虚函数重载报错1

class A
{
public:
    virtual void fun(int) = 0;
};
class B:public A
{
public:
    virtual void fun()
    {
        cout<<1<<endl;
    }
};
int main()
{
    B b1;
    b1.fun();
}

此时,由于A,B的fun()参数不同,B的fun相当于一个新的虚函数,B是虚基类,不能实例化,报错。

c++虚函数重载bug2

class A
{
public:
    virtual void fun() = 0;
};
class B:public A
{
public:
    virtual void fun()
    {
        cout<<1<<endl;
    }
};
int main()
{
    B b1;
    b1.fun();
}

此时,我们并不知道B的fun究竟是由于名字重复导致不小心重载了虚函数,还是B的fun真的要重载虚函数(默认后者!!!)。

对于报错1,加上override后

class A
{
public:
    virtual void fun(int) = 0;
};
class B:public A
{
public:
    virtual void fun() override
    {
        cout<<1<<endl;
    }
};
int main()
{
    B b1;
    b1.fun();
}

报错如下

C:\Users\asus\Desktop\Untitled2.cpp|21|error: 'virtual void B::fun()' marked 'override', but does not override

指出你标记了复写但是没有复写,啊哈哈哈。

对于2,加入final

class A
{
public:
    virtual void fun(int) = 0;
};
class B:public A
{
public:
    virtual void fun(int) final
    {
        cout<<1<<endl;
    }
};
class C:public B
{
public:
    virtual void fun(int)
    {
        cout<<"fuck!"<<endl;
    }
};

报错如下:

C:\Users\asus\Desktop\Untitled2.cpp|29|error: virtual function 'virtual void C::fun(int)' overriding final function

C复写了最终函数fun(int)

啊哈哈哈

class A
{
public:
    virtual void fun(int) = 0;
};
class B final:public A
{
public:
    virtual void fun(int)
    {
        cout<<1<<endl;
    }
};
class C:public B
{
public:
    virtual void fun(int)
    {
        cout<<"fuck!"<<endl;
    }
};

报错:

C:\Users\asus\Desktop\Untitled2.cpp|26|error: cannot derive from 'final' base 'B' in derived type 'C'

关于重载(overload),重写(override,也称覆盖), 重定义(redefine,也称隐藏):

一、重载(overload)
指函数名相同,但是它的参数表列个数或顺序,类型不同。但是不能靠返回类型来判断。
(1)相同的范围(在同一个作用域中) ;
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
(5)返回值可以不同;

二、重写(也称为覆盖 override)
是指派生类重新定义基类的虚函数,特征是:
(1)不在同一个作用域(分别位于派生类与基类) ;
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有 virtual 关键字,不能有 static 。
(5)返回值相同(或是协变),否则报错;<—-协变这个概念我也是第一次才知道…

(6)重写函数的访问修饰符可以不同。尽管 virtual 是 private 的,派生类中重写改写为 public,protected 也是可以的

所以,基本上可以说重载是更广义的复写,因此不再区分重载与复写的区别,一律重载。

三、重定义(也成隐藏)
(1)不在同一个作用域(分别位于派生类与基类) ;
(2)函数名字相同;
(3)返回值可以不同;
(4)参数不同。此时,不论有无 virtual 关键字,基类的函数将被隐藏(注意别与重载以及覆盖混淆) 。
(5)参数相同,但是基类函数没有 virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆) 。

其实就是覆盖了基类的函数。

(啥?你问我java的final咋弄?)

public:
const ....

等价于

public final ...


public:
void fun(...) final

等价于
public final void fun(...)


class A final{...};
class A final :public ...{};

等价于
final class A{...}
final class A extend ...{...}

(举例?就不举。明白事理远比写一堆没啥意思的测试代码有用)

六.float[10] arr;

首先,c++这样就不行。

报错一长串

java报错:Syntax error on token "10", delete this token

因为java不知道发什么疯把数组也弄成了一个类。联想到java左边的变量名类似于指针,显然c++没有这么玩指针的。因为读到10时为自动寻址,但是此时还没初始化呢,哪来的地址。

所以这两个在我看来其实差不多。 

public static void main(String[] args)
    { 
        float[] arr;
        arr = new float[]{1,2,3,4,5,6,7};
        for (int i = 0; i < arr.length; i++)
        {
            System.out.println(arr[i]);
        } 
    }
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#define ll long long
using namespace std;
int main()
{
    float *arr;
    arr = new float[10];
    for(int i = 0;i<10;i++)
    {
        *(arr+i) = i;
        cout<<*(arr+i)<<" ";
    }
}

至于数组元素时基本类型和引用类型的区别嘛,差不多就是一般数组和指针数组的区别。由于Java在代码表现上基本不能明显区分引用和实例,从代码上看差距不大,但原理差不多应该就是一般和指针的区别。

七. java 访问控制符

public,protect,private,default(包访问权限);

private :private。

default:包内为public,包外为private。

protected :包内public,包外的子类public,其余private

public:public

注意,不要闲着没事不写关键字,因为c++默认private,java默认同一package内所有成员开放,python在变量名上做文章确定权限。规范化描述不至于把自己写懵。(我自己的习惯)有必要开放就声明开放,没必要就声明不开放,包访问变量应该尽早声明。private与protected要细细思索应不应该给子类开放。

八.子类对父类属性与方法的继承。

参照上文,按照子类与父类在不在一个package内分类就行。

九。组合,重载,复写

类的组合:


class points
{
    private int x, y;
    points()
    {
        x = 0;
        y = 0;
    }
    points(int x,int y)
    {
        this.x = x;
        this.y = y;
    }
    int Getx() {return x;}
    int Gety() {return y;}
}
class lines
{
    private points l,r;
    lines()
    {
        this.l = new points();
        this.r = new points();
    }
    lines(int a,int b,int c,int d)
    {
        this.l = new points(a,b);
        this.r = new points(c,d);
    }
    void show()
    {
        System.out.println("l: ("+l.Getx()+","+l.Gety()+")");
        System.out.println("r: ("+r.Getx()+","+r.Gety()+")");
    }
}
public class test
{
    public static void main(String[] args)
    {
        lines a = new lines(1,2,3,4);
        a.show();
    }
}

类套类,只需要调用类的部分方法即可,相当与类指针。

class point
{
private:
    int x,y;
public:
    point()
    {
        x = y = 0;
    }
    point(int x,int y)
    {
        this->x = x;
        this->y = y;
    }
    int Getx()
    {
        return this->x;
    }
    int Gety()
    {
        return this->y;
    }
};
class lines
{
private:
    point *l,*r;
public:
    lines()
    {
        l = new point();
        r = new point();
    }
    lines(int a,int b,int c,int d)
    {
        l = new point(a,b);
        r = new point(c,d);
    }
    void show()
    {
        cout<<"l:("<<l->Getx()<<","<<l->Gety()<<")"<<endl;
        cout<<"r:("<<r->Getx()<<","<<r->Gety()<<")"<<endl;
    }
};
int main()
{
    lines *a = new lines(1,2,3,4);
    a->show();
    return 0;
}

几乎一样哈。

至于重载与复写,我记得写过了,似乎就在上面。


class points
{
    private int x, y;
    points()
    {
        x = 0;
        y = 0;
    }
    points(int x,int y)
    {
        this.x = x;
        this.y = y;
    }
    int Getx() {return x;}
    int Gety() {return y;}
}
class lines
{
    private points l,r;
    lines()
    {
        this.l = new points();
        this.r = new points();
    }
    lines(int a,int b,int c,int d)
    {
        this.l = new points(a,b);
        this.r = new points(c,d);
    }
    void show()
    {
        System.out.println("l: ("+l.Getx()+","+l.Gety()+")");
        System.out.println("r: ("+r.Getx()+","+r.Gety()+")");
    }
    //void Getx() {System.out.println(l.Getx()+" "+r.Getx());}
    //void Gety(){System.out.println(l.Gety()+" "+r.Gety());}
    //重载
    int Gety(){return Math.abs(r.Gety()-l.Gety());}
    int Getx(){return Math.abs(r.Getx()-l.Getx());}
    //复写
}
public class test
{
    public static void main(String[] args)
    {
        lines a = new lines(1,2,3,4);
        a.show();
        System.out.println(a.Getx()+" "+a.Gety());
    }
}

十. 子类实例化

(这玩意在一堆乱七八糟得东西里跳了好久,我受不了了啊啊啊啊啊啊!!!!!!!!!)

差不多就是执行初始化->执行子类构造->进入父类初始化->执行父类构造->执行父类剩余->执行子类剩余。

代码就不贴了

十一.互发消息

class A
{
    int a = 0;
    B b;
    boolean c = false;
    A()
    {
        a = 0;
        this.b = null;
    }
    A(B b)
    {
        a = 0;
        this.b = b;
        b.a = this;
    }
    void show()
    {
        if(c==true)
        {
            c = false;
            return;
        }
        else if(b!=null)
        {
            System.out.println("A:hey B!");
            if(b.c==true)
            {
                b.c = false;
                return ;
            }
            c = true;
            b.show();
        }
        else
        {
            System.out.println("not connected");
        }
    }
}
class B
{
    int b = 0;
    A a;
    boolean c = false;
    B()
    {
        b = 0;
        this.a = null;
    }
    B(A a)
    {
        b = 0;
        this.a = a;
        this.a.b = this;
    }
    void show()
    {
        if(c==true)
        {
            c = false;
            return;
        }
        else if(a!=null)
        {
            System.out.println("B:hey A!");
            if(a.c==true)
            {
                a.c = false;
                return;
            }
            c = true;
            a.show();
        }
        else
        {
            System.out.println("not connected");
        }
    }
}
public class test
{
    public static void main(String[] args)
    {
        //B b = new B();
        //A a = new A(b);
        A a = new A();
        B b = new B(a);
        //A a = new A();
        //B b = new B();
        System.out.println("A first:");
        a.show();
        System.out.println("B first:");
        b.show();
    }
}

前俩组输出一致,第三组会报not connected。

十二.组合与继承

组合相当于类中加引用类(指针),相当于friend。继承相当于继承父类的方法,相当于is a。

当类之间有联系但是差别过大时(比如鸟和飞机,除了会飞之外差距蛮大的),两者需要互动(鸟撞飞机,飞机躲避鸟),显然适合使用组合(飞机类里准备鸟的动态数组即可)。但是如果是有明显的子集关系(鸟和兀鹫之间),显然适合于继承的使用。

十三.java多态。

多态:父类的对象变量调用了子类中重写的方法。 

abstract class base
{
    String name = null;
    base()
    {
        name = null;
    }
    public abstract void show();
}
class dog extends base
{
    String habit = "chase cat";
    dog(String name)
    {
        super();
        this.name = name;
    }
    public void show()
    {
        System.out.println(name+" likes "+habit);
    }
}
class cat extends base
{
    String habit = "miao~";
    cat(String name)
    {
        super();
        this.name = name;
    }
    public void show()
    {
        System.out.println(name+" likes "+habit);
    }
}
public class test
{
    public static void main(String[] args)
    {
        base a = new cat("kitty");
        base b = new dog("spikes");
        a.show();
        b.show();
    }
}

输出是很显然的。

abstract class base
{
    String name = null;
    base()
    {
        name = null;
    }
    public abstract void show();
}
class dog extends base
{
    String habit = "chase cat";
    dog(String name)
    {
        super();
        this.name = name;
    }
    public void show()
    {
        System.out.println(name+" likes "+habit);
    }
    public void bomb()
    {
        System.out.println(name+" is setting the bomb");
    }
}
class cat extends base
{
    String habit = "miao~";
    cat(String name)
    {
        super();
        this.name = name;
    }
    public void show()
    {
        System.out.println(name+" likes "+habit);
    }
}
public class test
{
    public static void main(String[] args)
    {
        base a = new cat("kitty");
        base b = new dog("spikes");
        a.show();
        b.bomb();
        b.show();
    }
}

 这里仅仅加了一个专属dog的方法bomb,但是此时base引用无法调用子类dog特有的方法,报错显示base类未定义bomb方法。显然,通过调用父类的引用可以定向取用子类中重写父类的方法。但是不能取子类独有的方法。显然在代码层面无法确定父类引用会调用具体的那个方法,仅当运行时根据后面的具体对象进行动态绑定。

((dog)b).bomb();

神奇的是,对b进行向下转型后就可以用了,原因是此时b仅绑定dog实例,且唯一确定。

更神奇的是

#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#define ll long long
#define LoveLivesuperstar  cout<<"药药,切克闹,唐可可我最闪耀!!!"<<endl;
using namespace std;
class A
{
public:
    string name;
    A()
    {
        name = "";
    }
    virtual void show() = 0;
};
class B:public A
{
public:
    string habit;
    B()
    {
        name = "";
        habit = "chase cat";
    }
    B(string s)
    {
        name = s;
        habit = "chase cat";
    }
    void show()
    {
        cout<<this->name<<" likes "<<this->habit<<endl;
    }
    void run()
    {
        cout<<this->name<<" run!!!!"<<endl;
    }
};

int main()
{
    A *a = new B("spike");
    a->show();
    ((B*)(a))->run();
    return 0;
}

一模一样好吧,所以是谁抄谁的呢? 

十四.interface

interface Shape
{
    abstract void count();
    abstract void show();
}
class A implements Shape
{
    int a,b,c,ans;
    A()
    {
        a = b = c = 0;
        ans = -1;
    }
    A(int a,int b,int c)
    {
        this.a = a;this.b = b;this.c = c;
        ans = -1;
    }
    @Override
    public void count()
    {
        ans = a+b+c;
    }
    @Override
    public void show()
    {
        System.out.print(a+","+b+","+c);
        if(ans != -1)
        {
            System.out.print(","+ans);
        }
        System.out.println();
    }
}
class B implements Shape
{
    int a,b,ans;
    B()
    {
        a = b = 0;
        ans = -1;
    }
    B(int a,int b)
    {
        this.a = a;this.b = b;
        ans = -1;
    }
    @Override
    public void count()
    {
        ans = a+b;
    }
    @Override
    public void show()
    {
        System.out.print(a+","+b);
        if(ans != -1)
        {
            System.out.print(","+ans);
        }
        System.out.println();
    }
    public void change(int c)
    {
        a = c;
        ans = -1;
    }
}
public class test
{
    public static void main(String[] args)
    {
        Shape test1 = new A(1,2,3);
        Shape test2 = new B(1,2);
        B test3 = new B();
        test1.count();
        test1.show();
        test2.count();
        test2.show();
        //test2.change();
        ((B)(test2)).change(1);
        test3.show();
        test3.change(1);
    }
}

对于接口,就是一个纯粹的不能再纯粹的虚方法与静态成员及其方法的类,即虚方法与静态成员及其方法的集合。更像是一种啥具体的东西都没有的模板,需要自行继承,复写与填充特殊方法才能成型。在代码上和抽象类很像,甚至连向下转型都一样。

但是,抽象类存在非静态数据成员与方法,接口显然不可以有。实际上抽象类就是一个类,但是可以有自己的方法。同时,接口必须public,抽象类无所谓。抽象类接近is a,接口接近like a。

自不必说,上c++

#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#define ll long long
#define LoveLivesuperstar  cout<<"药药,切克闹,唐可可我最闪耀!!!"<<endl;
using namespace std;
class A
{
public:
    virtual void counts() = 0;
    virtual void show() = 0;
};
class B:public A
{
public:
    int a,b,c,ans;
    B()
    {
        a = b = c = 0;
        ans = -1;
    }
    B(int a,int b,int c)
    {
        this->a = a;
        this->b = b;
        this->c = c;
        ans = -1;
    }
    void counts()
    {
        ans = a+b+c;
    }
    void show()
    {
        cout<<a<<","<<b<<","<<c<<endl;
        if(ans!=-1)
        {
            cout<<ans<<endl;
        }
    }
    void another_show()
    {
        cout<<"啊哈哈哈哈哈哈"<<endl;
    }
};

int main()
{
    A *a = new B(1,2,3);
    a->counts();
    a->show();
    ((B*)(a))->another_show();
    return 0;
}

所以还是那个问题,谁抄谁的呢?

十五.equals

equals方法一般是判断两个引用是不是指向同一个对象,但是经过复写,往往变成比较内容是否一致。

相当于c++在使用指针或者一些大数组等情况时重载=与==与!=。

class A
{
    int b =0;
    A(int a)
    {
        this.b = a;
    }
    boolean equals(A b)
    {
        if(this.b != b.b)
        {
            return true;
        }
        return false;
    }
} 
public class test
{
    public static void main(String[] args)
    {
        A a1 = new A(1);
        A a2 = a1;
        A a3 = new A(1);
        System.out.println(a1.equals(a2)+" "+a1.equals(a3)+" "+a2.equals(a3));
    }
}

应该输出三个false,我故意的。

上c++

c++不能用指针重载,只能用实例的引用以友元函数重载/在类内重载,对比意义不大,不写了。

十六。instanceof

instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。

应用场景,上面的向下转型。

abstract class base
{
    String name = null;
    base()
    {
        name = null;
    }
    public abstract void show();
}
class dog extends base
{
    String habit = "chase cat";
    dog(String name)
    {
        super();
        this.name = name;
    }
    public void show()
    {
        System.out.println(name+" likes "+habit);
    }
    public void bomb()
    {
        System.out.println(name+" is setting the bomb");
    }
}
class cat extends base
{
    String habit = "miao~";
    cat(String name)
    {
        super();
        this.name = name;
    }
    public void show()
    {
        System.out.println(name+" likes "+habit);
    }
}
public class test
{
    public static void main(String[] args)
    {
        base a = new cat("kitty");
        base b = new dog("spikes");
        a.show();
        if(b instanceof dog)
        {
            dog c = (dog)b;
            c.bomb();
        }
        b.show();
    }
}

这样就不会有问题了呢

十七.抽象类与接口的异同

好像写过了呢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值