PurpleK's Studio

「今、君が好きで」


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于

Java堆栈,以及eqauls和==的区别

发表于 2016-08-04   |   分类于 Java

Java堆栈

Java把内存划分为两种:一种是堆,一种是栈。

栈

存放一些基本类型的变量和对象的引用变量。java自动释放掉所分配的空间,该内存空间可以立即被另作他用,存取速度比堆要快。

缺点是,存在栈中的数据大小与生存期必须确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(int,short,long,byte,float,double,boolean,char)和对象句柄。数据是可以共享的。

假设我们同时定义:

1
2
int a = 3;
int b = 3;

编译器先处理 int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没有找到,就将3存进来,然后讲a指向3,接着就处理 int b = 3;会先创建变量b的引用,因为栈中已经存在3这个值,那么就直接讲b指向3.如果这时在令a = 4,那么编译器会重新搜索栈中是否有4这个值,如果没有就讲4存进来,如果有就把a指向4,因此a不会影响到b的值。

要注意的是,这种数据共享与两个对象的引用指向同一个对象的这种共享不同,因为这种情况下a的修改不会影响到b的值,它是由编译器完成的,它有利于节省空间,而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

堆

存放由new创建的对象和数组(可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中这个变量就成了数组或对象的引用变量,就相对于一个名字。以后就可以使用栈中的引用变量来访问堆中的数组或对象。)。是有java虚拟机自动垃圾回收器来管理的。运行时动态分配空间。

因为运行时分配内存,存取速度较慢。

String str = new String("abc"); 这种是用new()来新建对象的,它会存放在堆中,每调用一次就会创建一个新的对象。

String str = "abc"; 这种是存放在栈中,创建一个String类的对象引用变量str,然后在栈中查找有没有存放abc,如果没有,则将abc存放在栈中,并令str指向abc,如果有abc,则直接令str指向abc。

比较类里面的数值是否相等,用equals()方法,比较两个包装类的引用是否指向同一个对象时,用==。

比如下面的代码:

1
2
3
4
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true;

输出为true,可以看出str1和str2是指向同一个对象的。这里是创建了两个abc字符串,在内存中其实只存在一个对象,这种写法有利于节省内存空间,同时它也可以在一定程度上提高程序的运行速度。因为jvm会自动根据栈中数据的实际情况来决定是否有必要创建新对象。

1
2
3
4
5
String str1 = new String("abc");
String str2 = new String("abc");
String str3 = "abc";
System.out.println(str1==str2); //false;
System.out.println(str1==str3); //false

因为用了new,生成了两个不同的对象,是在堆中创建新的对象,而不管其他字符串值是否相等,是有必要创建新对象,从而加重了程序的负担。

Android Studio cannot resolve symbol 解决办法

发表于 2015-09-25   |   分类于 Android

背景故事

上班中,渣渣电脑给我蓝屏了。蓝屏也就算了,还不自动重启。不重启也就算了,Android Studio还直接傻了。

能编译能运行,就是所有的类都提示”cannot resolve symbol”。

解决方法

重启了几次Android Studio都不行,然后就clean项目,再build,还是不行。

最后找到了这个方法:

点击菜单中的 “File” -> “Invalidate Caches / Restart”,然后点击对话框中的 “Invalidate and Restart”,清空 cache 并且重启。语法就会正确的高亮了。

记下来。方便以后找~

Android中传感器的values介绍

发表于 2015-09-15   |   分类于 Android

传感器

类型

  • TYPE_ACCELEROMETER 加速度传感器
  • TYPE_AMBIENT_TEMPERATURE 温度传感器(测量室温)
  • TYPE_GRAVITY 重力传感器
  • TYPE_GYROSCOPE 陀螺仪
  • TYPE_LIGHT 光传感器
  • TYPE_LINEAR_ACCELERATION 线性加速器
  • TYPE_MAGNETIC_FIELD 磁力传感器
  • TYPE_ORIENTATION 方向传感器
  • TYPE_PRESSURE 压力传感器
  • TYPE_PROXIMITY 距离传感器
  • TYPE_RELATIVE_HUMIDITY 相对湿度传感器
  • TYPE_ROTATION_VECTOR 旋转向量
  • TYPE_TEMPERATURE 温度传感器(设备温度)

注意

以下使用到的所有坐标系均以下图为准
坐标轴

加速度传感器(TYPE_ACCELEROMETER)

所有的数值都以(m/s^2)为单位:

  • values[0]: x轴减去重力轴x的加速度
  • values[1]: y轴减去重力轴y的加速度
  • values[2]: z轴减去重力轴x的加速度

因此在手机静止平放时,values[0]和values[1]应该是0,而values[2]应该为-g。(g为重力加速度)

磁力传感器(TYPE_MAGNETIC_FIELD)

所有的数值都是以微特斯拉(uT)为单位测量设备周围的x,y,z轴的磁力。

陀螺仪传感器(TYPE_GYROSCOPE)

values以r/s为单位来测量设备x,y,z的旋转速率。规定逆时针为正方向。

光传感器(TYPE_LIGHT)

values[0]: 以lux为单位表示周围的亮度

气压传感器(TYPE_PRESSURE)

values[0]: 以hPa为单位表示周围的气压

距离传感器(TYPE_PROXIMITY)

values[0]: 以cm为单位表示传感器到物体之间的距离

重力传感器(TYPE_GRAVITY)

三维向量表示重力的方向和大小。单位为m/s^2。

当设备静止的时候,重力传感器的输出恒等于加速度传感器的输出。

线性加速度传感器(TYPE_LINEAR_ACCELERATION)

三维向量表示设备x,y,z方向上的加速度但不包括重力。单位为m/s^2。

加速度传感器、重力传感器、线性加速度传感器的输出存在以下关系:

加速度传感器 = 重力传感器 + 线性加速度传感器

旋转向量传感器(TYPE_ROTATION_VECTOR)

旋转矢量用角和轴的组合来代表设备的取向,即设备绕着轴(X、Y或Z)旋转角度θ。

values分别是xsin(θ/2), ysin(θ/2), z*sin(θ/2)

(这个我也不太懂

方向传感器(TYPE_ORIENTATION)

方向传感器的值都是以度(degrees)为单位,

values[0]: Azimuth(向量的水平方向)。北极和y轴之间围绕z轴的角度。取值为0到359。0表示北方,90表示东方,180表示南方,270表示西方。

values[1]: Pitch(仰角)。绕x轴旋转的角度,z轴向y轴旋转为正方向。

values[2]: Roll。绕y轴旋转的角度,以设备顺势针旋转为正方向。

注意:该传感器为软件传感器,android已废弃。改为使用旋转矢量来计算。

湿度传感器

values[0]: 设备周围空气的相对湿度。

当相对湿度和室温测量出来之后,可以计算露点(dew point)和绝对湿度(absolute humidity)。
计算方法详见 此处

室温传感器(TYPE_AMBIENT_TEMPERATURE)

values[0]: 室温,以摄氏度为单位。

获取TextView显示的字符串宽度

发表于 2014-11-02   |   分类于 Android

工作上有业务需要判断textview是否换行,我的做法是判断textview要显示的字符串的宽度是否超过我设定的宽度,若超过则会执行换行。

项目中的其他地方也有这样的需求,故直接使用了那一块的代码。如下

1
2
3
4
5
6
public float getTextWidth(Context Context, String text, int textSize){
TextPaint paint = new TextPaint();
float scaledDensity = Context.getResource().getDisplayMetrics().scaledDensity;
paint.setTextSize(scaledDensity * textSize);
return paint.measureText(text);
}

这里是使用了TextPaint的measureText方法。

不过在项目实践上发现了这个方法存在一些问题。当字符串存在字母数字时,就会有1-2像素的误差。也正是这个误差,导致代码上判断换行错误,使得界面上显示出错。

为了解决这个问题,搜到了这篇文章 戳我

这篇文章中使用了另外一个方法测量,没有new TextPaint,而是使用了TextView自己的TextPaint,这个Paint通过TextView.getPaint()方法获得。


最后给出一个例子来看这两种方法的差别。

测试机是MI4,xxdpi

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 测试字符串
// 测试例子均用15sp的字体大小
String text = "测试中文";
TextView textView = (TextView) findViewById(R.id.test);
textView.setText(text);
int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
textView.measure(spec, spec);
// getMeasuredWidth
int measuredWidth = textView.getMeasuredWidth();
// new textpaint measureText
TextPaint newPaint = new TextPaint();
float textSize = getResources().getDisplayMetrics().scaledDensity * 15;
newPaint.setTextSize(textSize);
float newPaintWidth = newPaint.measureText(text);
// textView getPaint measureText
TextPaint textPaint = textView.getPaint();
float textPaintWidth = textPaint.measureText(text);
Log.i(TAG, "测试字符串:" + text);
Log.i(TAG, "getMeasuredWidth:" + measuredWidth);
Log.i(TAG, "newPaint measureText:" + newPaintWidth);
Log.i(TAG, "textView getPaint measureText:" + textPaintWidth);
}
}

当测试字符串为: “测试中文”时,结果如下

测试字符串:测试中文
getMeasuredWidth:180
measureText:180.0
getPaint measureText:180.0

当测试字符串为: “测试英文abcd”时,

测试字符串:测试英文abcd
getMeasuredWidth:279
newPaint measureText:278.0
textView getPaint measureText:279.0

可见使用textView的TextPaint调用measureText方法得到的宽度才是真正的宽度。

Yosemite上配置虚拟主机403 forbidden问题

发表于 2014-10-31   |   分类于 web

之前在10.9的时候配置了apache的虚拟主机,如下

1
2
3
4
5
6
7
8
9
10
11
12
<VirtualHost *:80>
DocumentRoot "/Users/PurpleK/Programming/web/root"
ServerName localhost
ErrorLog "/private/var/log/apache2/sites-error_log"
CustomLog "/private/var/log/apache2/sites-access_log" common
<Directory />
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order deny,allow
Allow from all
</Directory>
</VirtualHost>

我升级yosemite后,httpd.conf中的虚拟主机配置文件被注释了。

首先我把,include的#号去掉了。如下。

1
2
# Virtual hosts
Include /private/etc/apache2/extra/httpd-vhosts.conf

但是配置后,重启apache,出现了403的问题。

很奇怪,明明已经添加了allow from all了。

只好问google了。

最后找出这个帖子。 戳我

帖子中有这样一个回复:

If you are using virtual hosts you will probably need to change your configuration files somewhat. In particular you will need to change the following:

2.2 configuration:
Order allow,deny
Allow from all

2.4 configuration:
Require all granted

原来是2.4之后需要使用 Require all granted 来控制权限。

而yosemite上的apache是2.4.9版本。

最后在配置中添加上 Require all granted 就没有问题了。

12
PurpleK

PurpleK

{*≧∀≦}

9 日志
5 分类
7 标签
GitHub 微博
© 2016 PurpleK
由 Hexo 强力驱动
主题 - NexT.Pisces