码迷,mamicode.com
首页 > 编程语言 > 详细

From C# to Java (2) - 类的设计 (1)

时间:2015-06-29 19:47:22      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:

  上一篇文章 From C# to Java (1) - 类型、引用与相等关系 对 Java 与 C# 在基本概念上的一些区别进行了简单的叙述,在这里简单做一回顾。第一,Java 的数据类型分为基础数据类型和类类型,类类型均为引用类型;第二,Java 的“==”运算符严格执行引用相等;第三,Java 不支持运算符重载。其中的很多重要特性在本文中也会提到,而且对类设计有重要的意义。

  本文试图通过一个实际的 Java 类(Android Open Source Project 中的 BitmapFactory 类)作为例子,对 Java 的类设计特点加以介绍。有一个好消息是,事实上 Java 的类设计特性比 C# 简单一些,对开发人员而言,从 C# 转向 Java 难度并不大,主要区别于写法。

1 代码一览

  下面给出的就是 BitmapFactoy 类的代码,为了体现类设计的主体部分,部分具体实现被注释掉了,部分成员说明也被删减。因此,这段代码不能直接用于实际工程。请读者注意。BitmapFactoy 类是 Android 中用来进行外部图片资源解码的工厂类,通过这段代码,我们也可以对工厂类等概念的具体实现产生大致的印象。

  1 /*
  2  * Copyright (C) 2007 The Android Open Source Project
  3  *
  4  * Licensed under the Apache License, Version 2.0 (the "License");
  5  * you may not use this file except in compliance with the License.
  6  * You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 
 17 package android.graphics;
 18 
 19 import android.content.res.AssetManager;
 20 import android.content.res.Resources;
 21 import android.os.Trace;
 22 import android.util.DisplayMetrics;
 23 import android.util.Log;
 24 import android.util.TypedValue;
 25 
 26 import java.io.FileDescriptor;
 27 import java.io.FileInputStream;
 28 import java.io.IOException;
 29 import java.io.InputStream;
 30 
 31 /**
 32  * Creates Bitmap objects from various sources, including files, streams,
 33  * and byte-arrays.
 34  */
 35 public class BitmapFactory {
 36     private static final int DECODE_BUFFER_SIZE = 16 * 1024;
 37 
 38     public static class Options {
 39 
 40     public Options() {
 41             inDither = false;
 42             inScaled = true;
 43             inPremultiplied = true;
 44         }
 45 
 46         public Bitmap inBitmap;
 47 
 48         @SuppressWarnings({"UnusedDeclaration"}) // used in native code
 49         public boolean inMutable;
 50 
 51         /*...*/
 52 
 53         public boolean inPreferQualityOverSpeed;
 54 
 55         public int outWidth;
 56 
 57         public int outHeight;
 58         
 59         public String outMimeType;
 60 
 61         public byte[] inTempStorage;
 62 
 63         private native void requestCancel();
 64 
 65         public void requestCancelDecode() {
 66             requestCancel();
 67         }
 68     }
 69 
 70     public static Bitmap decodeFile(String pathName, Options opts) {
 71         Bitmap bm = null;
 72         InputStream stream = null;
 73         try {
 74             stream = new FileInputStream(pathName);
 75             bm = decodeStream(stream, null, opts);
 76         } catch (Exception e) {
 77             /*  do nothing.
 78                 If the exception happened on open, bm will be null.
 79             */
 80             Log.e("BitmapFactory", "Unable to decode stream: " + e);
 81         } finally {
 82             if (stream != null) {
 83                 try {
 84                     stream.close();
 85                 } catch (IOException e) {
 86                     // do nothing here
 87                 }
 88             }
 89         }
 90         return bm;
 91     }
 92 
 93     public static Bitmap decodeFile(String pathName) {
 94         return decodeFile(pathName, null);
 95     }
 96 
 97     public static Bitmap decodeResourceStream(Resources res, TypedValue value,
 98             InputStream is, Rect pad, Options opts) {
 99 
100         if (opts == null) {
101             opts = new Options();
102         }
103 
104         if (opts.inDensity == 0 && value != null) {
105             final int density = value.density;
106             if (density == TypedValue.DENSITY_DEFAULT) {
107                 opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
108             } else if (density != TypedValue.DENSITY_NONE) {
109                 opts.inDensity = density;
110             }
111         }
112         
113         if (opts.inTargetDensity == 0 && res != null) {
114             opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
115         }
116         
117         return decodeStream(is, pad, opts);
118     }
119 
120     public static Bitmap decodeResource(Resources res, int id, Options opts) {
121         /*...*/
122     }
123 
124     public static Bitmap decodeResource(Resources res, int id) {
125         return decodeResource(res, id, null);
126     }
127 
128     public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
129         /*...*/
130 
131     }
132 
133     public static Bitmap decodeByteArray(byte[] data, int offset, int length) {
134         return decodeByteArray(data, offset, length, null);
135     }
136 
137     private static void setDensityFromOptions(Bitmap outputBitmap, Options opts) {
138         /*...*/
139     }
140 
141     public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
142         /*...*/
143     }
144 
145     private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) {
146         // ASSERT(is != null);
147         byte [] tempStorage = null;
148         if (opts != null) tempStorage = opts.inTempStorage;
149         if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
150         return nativeDecodeStream(is, tempStorage, outPadding, opts);
151     }
152 
153     public static Bitmap decodeStream(InputStream is) {
154         return decodeStream(is, null, null);
155     }
156 
157     public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
158         /*...*/
159 
160     }
161 
162     public static Bitmap decodeFileDescriptor(FileDescriptor fd) {
163         return decodeFileDescriptor(fd, null, null);
164     }
165 
166     private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
167             Rect padding, Options opts);
168     private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
169             Rect padding, Options opts);
170     private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts);
171     private static native Bitmap nativeDecodeByteArray(byte[] data, int offset,
172             int length, Options opts);
173     private static native boolean nativeIsSeekable(FileDescriptor fd);
174 }

2 package 与 import

  package 用于说明该类位于哪个包(Package)下。类比 C# 的 Namespace 概念。

  import 用于引用其他类。类比 C# 用于引用其他类的 using 概念。

  import 也可以引入一个 Package 下的所有类,例如:

import android.util.*;

可以引入该包下的所有类,例如 Log 类、XML 与 JSON 相关类等等。

  在 Eclipse 环境下,快捷键 Ctrl + Alt + O 可以对所有 import 进行整理和排序;查看引用的快捷键为 F3。同时,在 Preferences 对话框(在 Window 菜单下)的 Java / Editor / Save Actions 中,还可以制定 IDE 在保存类时自动进行 import 的整理。

3 工厂类的声明,final 关键字

  Java 默认不能指定一个 package 中的类为静态(static),且只支持 public、protected 和 final 三个关键字。

  其中 final 关键字可类比 C# 中的 sealed 关键字(需要注意这种说法对于非 class 来说是不成立的。参考 http://stackoverflow.com/questions/1327544)。

  对 BitmapFactory 类的代码进一步简化:

 1 public class BitmapFactory {
 2     private static final int DECODE_BUFFER_SIZE = 16 * 1024;
 3 
 4     public static class Options {
 5     }
 6 
 7     public static Bitmap decodeFile(String pathName, Options opts);
 8 
 9     public static Bitmap decodeFile(String pathName);
10 
11     private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
12             Rect padding, Options opts);
13 
14     private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
15             Rect padding, Options opts);
16 
17     private static native Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts);
18 
19     private static native Bitmap nativeDecodeByteArray(byte[] data, int offset,
20             int length, Options opts);
21 
22     private static native boolean nativeIsSeekable(FileDescriptor fd);
23 }

可以发现,其所有成员变量与所有方法都采用了 static 修饰符。这一点与 C# 是类似的。

  另外,Java 要求 package 中的类的文件名与类名必须一致、包名与文件夹路径必须一致,不支持一个 .java 文件中写入多个类。

3 在类中声明类,访问器

  Java 支持在 class 中定义 class。在 BitmapFactory 中,Options 类记录了进行位图解码时需要用到的各种参数。在 C# 中它们更倾向于被声明为包含访问器的属性(Property)。

  由于 Options 类的特点,这里没有进行访问器封装。但是对于经常被访问的成员变量,仍然要求在类设计时完善访问器。Java 中没有在语言层面支持访问器,需要开发人员手动加入 Bar getFoo() 和 void setFoo(Bar value) 方法。

4 其他关键字

  @SuppressWarnings 用于指示编译器忽略下一行中潜在的指定 warning。

  native 是 JNI 的特性,声明为 native 的方法,其实现是使用 C/C++ 代码完成的。关于 JNI 的详情,请查阅 JNI 和 Android NDK 的相关资料。

5 总结

  由于成文比较草率,本文仅对一些明显的与 C# 不同的细节点进行了解释。而对于继承、接口等语言特性尚未加以介绍。这些内容将在今后以同样的形式加以补正。如对文中所述的内容存在疑问,或有任何意见和建议,烦请不吝赐教。

 

Flaris 原创
转载请注明出处
http://www.cnblogs.com/flaris
http://www.zhihu.com/people/flaris

From C# to Java (2) - 类的设计 (1)

标签:

原文地址:http://www.cnblogs.com/Flaris/p/4607221.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!