zoukankan      html  css  js  c++  java
  • 七、 面向对象(二)

      匿名类对象

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

    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"+"	"+"area");
            for(int i =1;i<= time;i++){
                c.setRadius(i);
                System.out.println(c.getRadius() + "	" + 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;
        }
    }
    构造器

         

  • 相关阅读:
    Aspnet_regsql.exe命令行使用小结
    ListView用法学习
    < %=...%>< %#... %>< % %>< %@ %>
    jQuery入门简介
    oracle基础琐碎总结删除数据
    WindowsPhone基础琐碎总结数据绑定(一)
    ADO.NET基础琐碎总结参数化查询
    oracle基础琐碎总结Where和Having的区别与联系
    第一次使用 Windows Live Writer
    WindowsPhone基础琐碎总结数据绑定(二)
  • 原文地址:https://www.cnblogs.com/Jeffding/p/8681442.html
Copyright © 2011-2022 走看看