day7 面向对象(二)

  匿名类对象

  创建的类的对象是匿名的。当我们只需要一次调用类的对象时,我们就可以考虑使用匿名的方式创建类的对象。特点是创建的匿名类的对象只能够调用一次!

package day007;

//圆的面积
class circle {
    double radius;
    public double getArea() {
        // TODO Auto-generated method stub
        return Math.PI * radius * radius;
    }

    public void setRadius(double r){
        radius = r;
    }

    public double getRadius(){
        return radius;
    }

    public void show(){
        System.out.println("我是一个圆");
    }

}

public class lambda{
    public void printArea(circle c, int time){
        System.out.println("radius"+"\t"+"area");
        for(int i =1;i<= time;i++){
            c.setRadius(i);
            System.out.println(c.getRadius() + "\t" + c.getArea());
        }
    }

    public static void main(String[] args){
        lambda p = new lambda();
        circle c = new circle();//新的圆半径为0
        p.printArea(c, 5);

        new circle().show();//这个对象就是匿名对象,只使用一次后就无法再次调用
    }
}

对象作为参数传递

  在上面这个例子里,我们使用new circle()直接调用circle的方法。这个对象就是匿名类对象,这个对象产生时,在内存堆中开辟内存存储了数据,但是在栈中并没有相应的变量名指向这块内存地址,那么我们无法再第二次调用这个匿名类,即我们不可以使用此类再次调用circle类的属性与方法。

  在java虚拟机中,这个匿名类对象很快就被垃圾回收机制收走了,切记,当我们某个类对象只需要使用一次的情况,我们才会考虑使用匿名类对象。

  可变个数的行参的方法:

  格式:对于方法的形参: 数据类型 ... 形参名;

  可变个数的形参的方法与同名的方法之间构成重载;

  可变个数的形参在调用时,个数从0开始,到无穷多个都可以。

  使用可变多个形参的方法与方法的形参使用数组是一致的。

  若方法中存在可变个数的形参,那么一定要声明在方法形参的最后。

  在一个方法中,最多声明一个可变个数的形参。

package day007;

public class javaArgs {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        javaArgs jargs = new javaArgs();
        jargs.getSum(1,2,3,4);
        new javaArgs().getSum(123,223);
        jargs.getSum("求和是", 2,3,5,8);
    }
//    public int getSum(int ... args){
    public void getSum(int ... args){
        int sum = 0;
        //args使用与数组一致
        for(int i = 0; i<args.length;i++){
            sum += args[i];
        }
        System.out.println(sum);
//        return sum;

    }
    //重载,可变个数的形参声明在方法形参的最后
    public void getSum(String s,int ... args){
        int sum = 0;
        for(int i = 0; i<args.length;i++){
            sum += args[i];
        }
        System.out.println(s + ":"+ sum);

    }
}

java的*args的使用

  java中形参与实参

  形参:方法声明时,方法小括号内的参数,实参:调用方法时,实际传入的参数的值。

  我们之前做的两个值转换:

package day007;

public class TestArgsTransfer {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //两个值转换
        int i = 10;
        int j = 5;
        System.out.println("i:" + i + " j:" + j);
        int temp = i;
        i = j;
        j = temp;
        System.out.println("i:" + i + " j:" + j);

    }

}

两个值交换

  然后你可能会想用一个类封装一个方法完成交换。然后你写了这样一个方法。

package day007;

public class TestArgsTransfer {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //两个值转换
        int i = 10;
        int j = 5;

        //封装到类方法
        TestArgsTransfer tt = new TestArgsTransfer();
        System.out.println("i:" + i + " j:" + j);
        tt.swap(i, j);//将i的值传递给m,j的值传递给n
        System.out.println("i:" + i + " j:" + j);
    }

    //定义一个方法,交换两个变量的值
    public void swap(int m,int n){
        int temp = m;
        m = n;
        n = temp;
        System.out.println("m:" + m + " n:" + n);
    }

}

你写的封装方法

  结果是你的i和j根本就没有变,为什么呢?

  简单来说就是i与j是你定义的类属性,你将i,j作为实参传到了类方法里面,类方法swap里的两个变量发生了位置转换,但是main中的两个值并没有发生任何变化,在内存中的表现如上图,调用swap方法时,会在栈中存两个swap的局部变量,这两个变量的值交换了,但是main的变量未发生改变。

  那我们要如何做呢。

package day007;

public class TestArgsTransfer1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TestArgsTransfer1 tt = new TestArgsTransfer1();
        DataSwap ds = new DataSwap();

        System.out.println("ds.i:" + ds.i + " ds.j:" + ds.j);

        tt.swap(ds);
        System.out.println(ds);

        System.out.println("ds.i:" + ds.i + " ds.j:" + ds.j);
    }

    //交换元素的值
    public void swap(DataSwap d){
        int temp = d.i;
        d.i = d.j;
        d.j = temp;
        System.out.println(d);//打印引用变量d的值
    }
}

class DataSwap{
    int i = 10;
    int j = 5;
}

形参是引用数据类型

  这里swap方法传入的是一个引用数据类型ds,相当于d与ds一致都指向同一个堆空间,那么在swap中完成两个值的交换。

  练习一下,下面代码的执行结果是什么:

class Value {
    int i = 15;
}

class TestValue {
    public static void main(String argv[]) {
        TestValue t = new TestValue();
        t.first();
    }

    public void first() {
        int i = 5;
        Value v = new Value();
        v.i = 25;
        second(v, i);
        System.out.println(v.i);
    }

    public void second(Value v, int i) {
        i = 0;
        v.i = 20;
        Value val = new Value();
        v = val;
        System.out.println(v.i + " " + i);
    }
}

  分析:

  第一步,定义了TestValue类,在类的main函数中,生成一个实例t,并在堆中开辟内存(0x0001),在栈中定义t指向堆中内存0x0001。实例调用实例的first方法。

  第二步,在栈中有局部变量i值为5,一个新的变量v,指向堆中新开辟内存(0x0011),v的局部变量i值为25,将v与当前局部变量i=5作为实参传给second方法。

  第三步,局部变量i的值改为0,v的局部变量i变为20,定义一个新变量val指向堆中先开辟内存(0x0111),second中实参v指向内存(0x0111)

  第四步,此时打印v.i值为内存0x0111中的i,值为15,i为局部空间中的变量i为0,first打印的v.i值为20(实参传入first,v本身未发生指向的改变)。

  面向对象:封装

  我们考虑不让对象来直接作用属性,而是通过"对象.方法"的形式,来控制对象对属性的访问。实际情况中,对属性的要求就可以通过方法来体现。

  两种方法:①将类的属性私有化,②提供公共的方法(setter & getter)来实现调用。

package day007;

public class java_private {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Animal an = new Animal();
//        an.legs = 4;//飘红
        an.setLegs(4);
        an.getLegs();
    }

}

class Animal{
    private String name;
    private int legs;

    public void setLegs(int l){
        legs = l;
    }

    public int getLegs(){
        System.out.println(legs);
        return legs;
    }
}

私有封装

  权限修饰符

  构造器

  也就是构造方法,但是与python的__init__有相似之处,但是不完全一致。

  构造器的作用:①创建对象 ②给创建的对象的属性赋值(创建对象的话,相当于python中的__new__与__init__的作用)。

  1.设计类时,若不显式声明类的构造器的话,程序会默认提供一个空参的构造器

  默认加()就相当于调用了构造器了,类比python加()后实例化即调用了构造方法。

  2.一旦显式的定义类的构造器,那么默认的构造器就不再提供。

  3.如何声明类的构造器。格式:权限修饰符  类名(形参){ }。

   4.类的多个构造器之间构成重载。

  类对象的属性赋值的先后顺序:①属性的默认初始化 ②属性的显式初始化③通过构造器给属性初始化 ④通过"对象.方法"的方式给属性赋值。

package day007;

public class init {
    public static void main(String[] args) {
        Person p1 = new Person();
        System.out.println(p1.getName() + ":" + p1.getAge());
        String str = new String("hello");
        System.out.println(str);

        Person p2 = new Person("jeff");
        System.out.println(p2.getName());
        System.out.println(p2.getAge());

        Person p3 = new Person("frank",23);
        System.out.println("name:" + p3.getName() + " age:" + p3.getAge());
        //体会属性赋值的过程
        Person p4 = new Person();
        System.out.println("name:" + p4.getName() + " age:" + p4.getAge());

        Person p5 = new Person(12);
        System.out.println("name:" + p5.getName() + " age:" + p5.getAge());
    }
}

class Person{
    //属性
    private String name;
    private int age = 1;

    //构造器
    public Person(String n){
        name = n;
    }
    public Person(){
//        age = 10;
//        name = "张三";
    }
    public Person(int a){
        age = a;
    }
    public Person(String n,int a){
        name = n;
        age = a;
    }

    //方法
    public void setName(String n){
        name = n;
    }
    public void setAge(int a){
        age = a;
    }
    public String getName(){
        return name;
    }
    public int getAge(){
        return age;
    }
}

构造器

   本节代码托管到我的github:day007。  

原文地址:https://www.cnblogs.com/Jeffding/p/8681442.html

时间: 2024-10-23 10:12:21

day7 面向对象(二)的相关文章

Python之路,Day7 - 面向对象编程进阶

本节内容 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业开发一个支持多用户在线的FTP程序 面向对象高级语法部分 静态方法 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法什么是静态方法呢其实不难理解普通的方法可以在实例化后直接调用并且在方法里可以通过self.调用实例变量或类变量但静态方法是不可以访问实例变量或类变量的一个不能访问实例变量和类变量的方法其实相当于跟类本身已经没什么关系了它与类唯一的关联就是需要通过

php面向对象(二) $this

<!doctype html> <html> <head> <meta charset="UTF-8"> <title>this</title> </head> <body> <?php //对象一旦被创建 对象中的每个成员方法里面都会存在一个特殊的对象引用"$this" 成员方法属于哪个对象 $this引用就代表哪个对象 专门用来完成对象内部成员之间的访问 cla

Python全栈开发,Day7 - 面向对象学习

本章内容 面向对象编程介绍 面向对象开发 面向对象的特性 一.面向对象编程介绍 介绍之前,先说一个例子: 你的老板要你做一款枪战游戏,游戏里面有很多的角色,比如CF里面的潜伏者和保卫者,在游戏里还有很多的玩家,每个玩家都有不同的名字和装扮,但是你发现这些玩家同一个阵容(潜伏者.保卫者)里的玩家具有很多相同的属性,于是你开始写代码,首先定义潜伏者1,名字.武器......等,然后保卫者1,同样,名字.武器......:代码如下: 1 def defenders(name,weapon,*args)

PHP面向对象(二)

一.概念 封装性是面向对象编程中的三大特性之一,封装就是把对象中的成员属性和成员方法加上访问修饰符,使其尽可能隐藏对象的内部细节,以达到对成员的访问控制(切记不是拒绝访问). 含义: a.把对象的全部成员属性和全部成员方法结合在一起,形成一个不可分割的独立单位(即对象) b.信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界(或者说形成一道屏障),只保留有限的对外接口使之与外部发生联系. 原则:要求对象以外的部分不能随意存取对象的内部数据(成员属性和成员方法),从而有效的避免了外部错  误对

python小白-day7 面向对象高级部分

python 面向对象(进阶篇) 本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员以及类的反射. 类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份. 一.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同. 普通字段属于对象 静态字段属于类 1 2 3 4 5

day7 面向对象进阶

面向对象高级语法部分 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法. class SchoolMember(object): def __init__(self,name,age,sex):

python面向对象二

1.1类的静态属性,类方法,类的静态方法 1.1.1静态属性(@property) 在类中: python内置的@property装饰器就是负责把一个方法(函数)变成属性来调用. class Student: def __init__(self,name,age,score): self.name = name self.age = age self.score = score @property def get_score(self): return self.score def learn(

python面向对象(二)

类的成员 类的成员可以分为三大类:字段.方法和属性 一.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 class foo: # 字段(静态字段,保存在类里) cc = '111' def __init__(self): # 字段(普通的字段,保存在对象里) self.name = 'mxz' def f1(self): print(self.name) class Province: # 静态字段 cou

Python自动化开发 - 面向对象(二)

本节内容 1.isinstance(obj,cls)和issubclass(sub,super) 2.反射 3.__setattr__,__delattr__,__getattr__ 一. isinstance(obj,cls)和issubclass(sub,super) 1.isinstance(obj,cls) 检查obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstance(obj, Foo)) # True 2.