Just Be Unreserved!

学无止境。


  • 首页

  • 分类

  • 归档

  • 标签

  • 关于

CentOS下SVN服务器的搭建使用

发表于 Apr 1 2013   |   分类于 Linux   |  

SVN作为新一代代码版本管理工具,有很多优点,管理方便,逻辑明确,安全性高,代码一致性高。SVN数据存储有两种方式,BDB(事务安全表类型)和FSFS(一种不需要数据库的存储系统),为了避免在服务器连接中断时锁住数据,FSFS是一种更安全也更多人使用的方式。SVN的运行方式也有两种,一种是独立服务器,另一种是借助apache服务,各有利弊,下面就介绍一下这两种方式各自的部署步骤。

##作为独立服务器运行:

①安装svn

1
yum install svn

②创建版本库

1
2
mkdir /svn/project    #创建版本库所在文件夹
svnadmin create--fs-type fsfs /svn/project/first #创建版本库,如果需要使用bdb方式存储,则将fsfs改成bdb即可

③初始化版本库,即导入文件到版本库中

1
2
svn import /home/software file:///svn/project/first--message "初始化版本"  #将home文件夹的文件导入版本库
svn list --verbose file:///svn/project/first #查看导入的文件

④启动svn服务,svn服务默认端口为3690,可以使用“netstat -ntlp”命令查看服务启动是否成功

1
svnserve -d -r /svn/project/first

⑤修改策略控制文件,vi authz,如果以后要添加用户,就将用户名加在相应的用户组(admin或者user)后面即可

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
### This file is an example authorization file for svnserve.
### Its format is identical to that of mod_authz_svn authorization
### files.
### As shown below each section defines authorizations for the path and
### (optional) repository specified by the sectionname.
### The authorizations follow. An authorization line can refer to:
### - a single user,
### - a groupof users defined in a special [groups] section,
### - an alias defined in a special [aliases] section,
### - all authenticated users, using the '$authenticated' token,
### - only anonymous users, using the '$anonymous' token,
### - anyone, using the '*' wildcard.
###
### A match can be inverted by prefixing the rulewith'~'. Rules can
### grantread ('r') access, read-write ('rw') access, orno access
### ('').
[aliases]
# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average
[groups]
# harry_and_sally = harry,sally
# harry_sally_and_joe = harry,sally,&joe
admin=first,second,third #用户组admin包含的成员
user=anyone #用户组user包含的成员
# [/foo/bar]
# harry = rw
# &joe = r
# * =
# [repository:/baz/fuz]
# @harry_and_sally = rw
# * = r
[/]
@admin=rw #用户组admin内成员拥有读写权限
@user=r #用户组user内成员拥有读权限

⑥添加svn访问用户,vi passwd,为authz里分配的用户设置密码,等号左边为用户名,等号右边是密码;

1
2
3
4
5
6
7
8
9
10
11
### This file is an example password file for svnserve.
### Its format is similar to that of svnserve.conf. As shown in the
### example below it contains one section labelled [users].
### The nameandpasswordfor each user follow, one account per line.
[users]
# harry = harryssecret
# sally = sallyssecret
first=first
second=second
third=third
anyone=anyone

⑦修改svn读取的权限策略文件

1
vi /svn/project/first/conf/svnserve.conf:

1
2
3
4
anon-access = none  #不允许匿名用户读写
auth-access = write
password-db = passwd #svn读取的passwd文件
authz-db = authz #svn读取的权限控制文件

⑧安装svn客户端,就可以使用客户端通过如下的url就可以访问了

1
svn://IP地址/svn/project/first

##借助apache服务器,通过web端访问svn

①给apache服务器安装两个svn插件,这两个插件同样可以使用yum安装

1
2
yum install mod_dav_svn   #使subversion与dav模块通信的功能
yum install mod_authz_svn #实现权限控制功能

②使用命令“httpd -M”可以查看是否加载这两个模块,如加载,则有如下回应:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Loaded Modules:
core_module (static)
mpm_prefork_module (static)
http_module (static)
so_module (static)
auth_basic_module (shared)
auth_digest_module (shared)
authn_file_module (shared)
authn_alias_module (shared)
authn_anon_module (shared)
authn_dbm_module (shared)
authn_default_module (shared)
authz_host_module (shared)
authz_user_module (shared)
authz_owner_module (shared)
authz_groupfile_module (shared)
authz_dbm_module (shared)
authz_default_module (shared)
ldap_module (shared)
authnz_ldap_module (shared)
include_module (shared)
log_config_module (shared)
logio_module (shared)
env_module (shared)
ext_filter_module (shared)
mime_magic_module (shared)
expires_module (shared)
deflate_module (shared)
headers_module (shared)
usertrack_module (shared)
setenvif_module (shared)
mime_module (shared)
dav_module (shared)
status_module (shared)
autoindex_module (shared)
info_module (shared)
dav_fs_module (shared)
vhost_alias_module (shared)
negotiation_module (shared)
dir_module (shared)
actions_module (shared)
speling_module (shared)
userdir_module (shared)
alias_module (shared)
substitute_module (shared)
rewrite_module (shared)
proxy_module (shared)
proxy_balancer_module (shared)
proxy_ftp_module (shared)
proxy_http_module (shared)
proxy_ajp_module (shared)
proxy_connect_module (shared)
cache_module (shared)
suexec_module (shared)
disk_cache_module (shared)
cgi_module (shared)
version_module (shared)
authz_ldap_module (shared)
dav_svn_module (shared)
authz_svn_module (shared)
Syntax OK

③编辑apache服务配置文件vi /etc/httpd/conf/httpd.conf,加入下面几行:

1
2
3
4
5
6
7
<Location /svn>
DAV svn
SVNPath /svn/project/first
AuthzSVNAccessFile /etc/httpd/conf.d/authz #apache服务器读取的权限策略文件
AuthType Basic
AuthName "Project"
AuthUserFile /etc/httpd/conf.d/passwd #apache服务器读取的密码存储文件

④编辑文件authz放在文件夹/etc/httpd/conf.d中,文件格式同文章上面的那个authz文件,编辑文件passwd放在文件夹/etc/httpd/conf.d中,使用如下命令生成用户名和密码

1
htpasswd -c /svn/project/first admin  #命令为htpasswd,-c为参数,/svn/project/first为访问的版本库,admin为用户名

然后重复输入你想设置的密码就可以自动存储在文件passwd中,默认为md5存储。

⑤重启apache服务,就可以在网页端使用刚才设置的用户名密码访问了,网址为http://IP地址:端口/svn

##配置多项目创建维护:

其实过程也比较简单,只需要在原来的基础上修改一点信息就可以了。

举个例子,比如有first和second两个项目,要实现多项目的启动管理,只需要修改对应项目配置文件authz的管理路径即可,如下:

###单项目:

1
2
3
[/]
@admin=rw
@user=r

启动:

1
svnserve -d -r /svn/project/first

或者

1
svnserve -d -r /svn/project/second

无法同时启动多个项目,因此也就无法同事访问多个项目;

###多项目:

1
2
3
4
5
6
[first:/]
@admin=rw
@user=r
[second:/]
@admin=rw
@user=r

启动:

1
svnserve -d -r /svn/project/

这样就可以启动所有project下的项目了。

很容易理解,但项目里的“/”代表项目根目录,可以使这样“/svn/project/first”或者“/svn/project/second”,多项目里的“/”代表“/svn/project”,在此基础上加上“first:”或者“second:”就切到对应项目里了。

RedHat和CentOS使用本地yum源配置

发表于 Mar 20 2013   |   分类于 Linux   |  

使用yum命令安装所需的软件,如果设备网络状况很好,当然也没必要去配置本地yum源,直接使用命令“yum install + 软件名字”即可。

如果由于一些原因,无法使用网络或者网络状况不好,使用本地yum源会很方便。

RedHat和CentOS的操作步骤基本一致,略有不同。

1、首先介绍一下RedHat中yum源的配置:

①挂载镜像:

1
2
3
mkdir /mnt/cdrom 
cd /mnt/cdrom
mount /dev/cdrom /mnt/cdrom

②修改配置文件:

1
cd /etc/yum.repos.d

③ls查看文件,使用mv命令将列出的文件都备份一下,格式如下:

1
mv RedHat-Base.repo RedHat-Base.repo.bak

④新建yum源配置文件:

1
vi RedHat.repo

⑤具体配置文件内容如下:

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
[Server] 

name=Server

baseurl=file:///mnt/cdrom/Server

gpgcheck=0

enable =1

[VT] name=VT

baseurl=file:///mnt/cdrom/VT

gpgcheck=0

enable =1

[Cluster]

name=Cluster

baseurl=file:///mnt/cdrom/Cluster

gpgcheck=0

enable =1

[ClusterStorage]

name=ClusterStorage

baseurl=file:///mnt/cdrom/ClusterStorage

gpgcheck=0

enable =1

2、CentOS本地yum源配置前面的步骤跟RedHat都一样,只是配置文件内容比RedHat要少一下,如下:

1
2
3
4
5
6
7
8
9
[CentOS] 

name=CentOS

baseurl=file:///mnt/cdrom

gpgcheck=0

enable=1

至此,就可以直接使用“yum install + 软件名字”命令安装镜像里存在的软件包了。

ListView控件的使用

发表于 Feb 1 2013   |   分类于 Android   |  

ListView是一个用于列表显示数据的高级控件。

使用ListView控件的前提条件是每个条目都非常类似。

使用ListView必须要有适配器,除了可以自定义适配器,常用的适配器还有ArrayAdapter(数组适配器)和SimpleAdapter(简单适配器),这些适配器都是继承了BaseAdapter,实现BaseAdapter中的getCount(),getItem(int position),getItemId(int position),getView(int position, View convertView, ViewGroup parent)这四个方法。

##ArrayAdapter的使用##

1
2
3
4
5
6
7
8
9
10
11
//数组适配器
String[] objects = new String[]{"a","b","c","d","e","f","g","h","i"};
ListView lv = (ListView) findViewById(R.id.lv);

//ArrayAdapter只能显示文本控件 并且只能是一个文本控件
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,//上下文
android.R.layout.simple_list_item_1,//条目的布局 android系统底层会有一些简单的布局 引用android底层的资源
android.R.id.text1,//条目里面的控件的id
objects);//要显示的数据
lv.setAdapter(adapter);
//如果以后开发看到简单的文字列表显示那么使用ArrayAdapter是最方便

##SimpleAdapter的使用##

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//简单适配器
String[] objects = new String[]{"a","b","c","d","e","f","g","h","i"};
ListView lv = (ListView) findViewById(R.id.lv);

String[] from = new String[]{"name","age"};
int[] to = new int[]{android.R.id.text1,android.R.id.text2};
final SimpleAdapter adapter = new SimpleAdapter(this,//上下文
data,//数据 List<? extends Map<String, ?>> data
android.R.layout.simple_list_item_2,//条目的布局文件
from,//String[] from 数据从哪里来
to);//int[] to
lv.setAdapter(adapter);
//给ListView的条目设置条目点击监听
lv.setOnItemClickListener(new OnItemClickListener() {
//点击条目的时候,方法别调用 int position 条目的位置
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//适配器提供了一个方法getItem(position) 可以获取条目对应的数据
Map<String,Object> map = (Map<String, Object>) adapter.getItem(position);
String text = "姓名:"+map.get("name")+",age:"+map.get("age");
Toast.makeText(getApplicationContext(), text, 1).show();
}
});

##开发中ListView的使用步骤##

  1. 在布局中写好ListView控件;
  2. 使用findViewById(R.id.lv)获取空间;
  3. 给ListView设置适配器lv.setAdapter();

其中重点和难点都是给ListView设置适配器这部分:

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
40
41
42
43
44
45
//自定义适配器继承BaseAdapter
private class MyAdapter extends BaseAdapter{

private Context context;
private List<Student> students;
//布局加载器
private LayoutInflater mInflater;
public MyAdapter(Context context, List<Student> students) {
super();
this.context = context;
this.students = students;
mInflater = LayoutInflater.from(context);
}

//获取ListView条目的数量
public int getCount() {
return students.size();
}

public Object getItem(int position) {
return students.get(position);
}

public long getItemId(int position) {
return 0;
}

public View getView(int position, View convertView, ViewGroup parent) {
//使用布局加载器加载布局文件,此处的ViewGroup指向ListView,只是加载布局,而不是加在内容,因此应为null
View view = mInflater.inflate(R.layout.item, null);
//从view中获取对应的控件
//findViewById(id); findViewById(id)是加载Activity布局文件的控件,而此处是从view中获取对应控件,因此一定不能忘记要使用下面的方式获取,前面要加上view
TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
TextView tv_age = (TextView) view.findViewById(R.id.tv_age);

//获取条目对应的数据
Student student = students.get(position);

//把数据绑定给指定的控件
tv_name.setText(student.name);
//age是int类型,而setText()方法传入的参数有两种形式,一种是String,直接将需要的属性传进去,还有一种是int,这个int指的是resid,即资源id,会出现资源找不到异常
tv_age.setText(student.age+"");
//返回view,一定要返回view,否则会出现空指针异常
return view;
}

上面的代码里,其中创建ListView显示的条目又可以分为以下几个步骤:

View getView() {

  • 使用布局加载器加载布局;
  • 找到布局中的控件;
  • 找到条目对应的数据;
  • 把数据绑定给对应控件;
  • 返回条目

}

离职感想

发表于 Jan 16 2013   |   分类于 感悟   |  

要离开公司了,人生历程第一份工作,总觉得应该分外珍惜,可惜事与愿违,如今却离开了。有了更好的选择就离开。更好的选择有时候是很难想得开的东西,有的人理解待遇好就都好,有的人理解公正的评价对自己很重要,有的人未雨绸缪找好了退路,有的人则更看重舒适的工作环境,更甚至有人觉得单纯地选择离开就比留下更适合自己……最近大雾比较严重,很多人都选择了戴口罩,我却固执地选择坚决不戴,这并不是说我不讲卫生、不注重自己的身体健康,因为我有鼻炎,戴上口罩呼吸说话都不方便,所以不戴口罩才是更好的选择。

不管怎样,总得留下点以后用以几年的寄托,所以对我来说,现在最要紧的任务就是完成这篇日志,表达我对各位朋友的感谢。希望各位都记得我的好,忘掉我的不好,即使忘不掉,也请不要让我知道。如果其中哪一位对我不满,打过我小报告或者给我穿过小鞋,都请永远不要让我知道。

老赵,我进公司第一个近距离接触的人,带我去的西区,带我回的东区,对所有的实习生都像是已经相处很久的老朋友,总能最真诚对每一个人,对他我要表达的不仅是感谢,他更是我的榜样,学习的目标。离开了,现在依然是邻居,总说要邀请老赵去我家吃饭,尝尝我的手艺,总被各种托辞拒绝,其实我想说我真的会做菜。以后,也许还有机会吧。

西勇,算是在公司对我帮助最大的一个人吧,现在我所掌握的技能知识,几乎全部都是西勇教给我的,我也把他当作自己的大哥来看待。平常工作里,我出了很多问题,给西勇造成很多麻烦,每次自己也很沮丧,但是他也从来没责怪过我,总是很耐心地帮我纠正,作为我最直接的领导,我要说抱歉,更要说谢谢。

郑浩,我进公司后第一个对我有重要影响的人,永远也忘不了在西区那段很短很短的日子。现在想想仍然怀念,如果一直是那个时候该多好……那个时候,我们坐的最近,接触最多,他讲的挂接数据源刚好也是那时候我掌握的最深的一段,虽然那时候所谓的学习都是很皮毛,现如今其他人讲的什么我是真的不记得了。

道远,是领导,也是学长。对他有佩服,有敬畏,接触的不多,但依然很感谢。现在想想,其实除了小欢,道远算是我见到的公司里的第一个人,比面试我的老板还要早。不过,估计他已经忘了。在他的领导下,我是我们那一批进公司中的第一个成项目经理的,而且真正意义上的出差也完全是我一个人,所有工作也都是一个人独立完成,虽然中间犯了很多错误,有一些不愉快,可当初我仍觉得这样的挑战和机会是自己的幸运,如今想来,却也有些迷惘了。

张阳、海杰、苗、高贺、刘坤、弘天的小甘和罗炜,这都是朋友了,不管他们是不是真当我是朋友,我是真的当他们是朋友了。现在想想是有蛮多遗憾的,经常在一起聊着说要团购,一起去吃东西,竟然一直到离开都没有机会。当然朋友之间经常调侃开玩笑,如果过火也可能会有一些不愉快,可我现在是什么都不记得了,我想他们也都不记得了。因为我觉得朋友应该是一辈子的。

恺哥,是学长,还是老乡,对我也是各种关照,希望以后在家里也能再见到他。还有环哥,当初去参加他的婚礼,上了200块的红包,因为考虑到我刚毕业就一身的债,又回给我100,代替他那段时间,也给他添了很多麻烦,实在对不起,还有万分地感谢。老曹,算是我从敬畏慢慢到熟悉以致越来越喜欢和尊重的一个人吧,难得有领导像他那样平易近人。当然还有金亭姐,就像母亲一样照顾着我们一群人,每次出差回来都给她造成很多麻烦,心里很过意不去,一直包容我的过错。传军,一些同事觉得他有些行为比较2,我倒觉得传军是难得的率真,像《步步惊心》里的十阿哥,跟他相处觉得非常容易,心里不用想任何东西。还有很多同事,都一并谢谢了。

说到感谢,更少不了晓兵,这是惟一一个接触过的销售,从他身上我学到了很多,许多东西别人可以教,但是他是惟一一个用亲身经历让我明白许多道理的人,我总觉得自己身上有一些东西很不适合现在的社会,那些自己曾经很引以为傲的、也曾被很多人认为是非常优秀的品质,现在看来都是幼稚。稍微有一点理想化的书生意气好像都活不下去,虽然自己以前经常会有努力去面对现实的想法,但是好像总也抹不去那份天真。也许等到自己以前不认同的东西都变成自己骨子里怎么也擦不掉的印记,我就更适合好好活下去了。

还有最该谢谢的,一直陪伴我的那个人,一直喊累,虽然她都不信……终于可以休息下了,其实我想说在决定要离开与真正离开之前这段时间是最累的。现在不工作了,也想说声对不起。

Java继承

发表于 Jul 25 2012   |   分类于 Java   |  

##什么是继承?

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

多个类可以称为子类,单独这个类称为父类、超类或者基类。

子类可以直接访问父类中的非私有的属性和行为。

通过 extends 关键字让类与类之间产生继承关系。

1
class SubDemo extends Demo{}	//SubDemo是子类,Demo是父类

##继承有什么好处?

  • 提高代码的复用性。
  • 让类与类之间产生了关系,是多态的前提。

##继承的特点

  1. Java只支持单继承,不支持多继承。

    1
    2
    3
    //一个类只能有一个父类,不可以有多个父类。
    class SubDemo extends Demo{} //ok
    class SubDemo extends Demo1,Demo2...//error
  2. Java支持多层(重)继承(继承体系)。

    1
    2
    3
    class A{}
    class B extends A{}
    class C extends B{}

##使用继承时的注意事项

  • 如果类之间存在着:is a 的关系,就可以考虑使用继承。
  • 不要为了继承部分功能,而去使用继承。

##super和this有什么区别?

super是一个关键字,代表父类的存储空间标识。(可以理解为父亲的引用)

super和this的用法相似。

this代表对象的引用(谁调用就代表谁);
super代表当前子类对父类的引用。

使用场景

  • 当子父类出现同名成员时,可以用super进行区分;
  • 子类要调用父类构造函数时,可以使用super语句。

区别

  1. 成员变量
    this.变量    --    本类的
    super.变量    --    父类的
    
  2. 构造方法
    this(...)    --    本类的
    super(...)    --    父类的
    
  3. 成员方法
    this.方法名()    --    本类的    
    super.方法名()    --    父类的
    

super();和this();都是在构造函数的第一行,不能同时出现。

##方法的重写(覆盖)

子类中出现与父类一模一样的方法时(除了权限修饰符,权限修饰符大于等于不包括private,返回值类型,方法名和参数列表相同),会出现覆盖操作,也称为重写或者复写。

父类私有方法,子类看不到,因此父类私有方法的重写也就无从谈起。

覆盖注意事项:

  • 覆盖时,子类方法权限一定要大于等于父类方法权限;
  • 静态只能覆盖静态。

覆盖的使用场景:

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容。

方法重写和重载有什么区别?

方法的重写用在子类方法与父类方法一模一样时,除权限修饰符,返回值类型,方法名和参数列表都是相同的。
重载用在同一个类中各方法方法名相同,参数列表不同(与返回值类型没有关系)的情况。

子父类中构造方法的用法:

  1. 子类的初始化过程中,首先回去执行父类的初始化动作。

    因为子类的构造方法中默认有一个super()。子类要使用父类的成员变量,这个初始化,必须在子类初始化之前完成。所以,子类的初始化过程中,会先执行父类的初始化。

  2. 如果父类没有无参构造方法
  • 使用super调用父类的带参构造。推荐方式。
  • 使用this调用本身的其他构造。

静态代码块、构造代码块,构造方法的执行顺序:

父类静态代码块→子类静态代码块→父类构造代码块→父类构造方法→子类构造代码块→子类构造方法

##final关键字

final是一个关键字,可以用于修饰类,成员变量,成员方法。

特点:

  1. 它修饰的类不能被继承。
  2. 它修饰的成员变量是一个常量。
  3. 它修饰的成员方法是不能被子类重写的。

final修饰的常量定义一般都有书写规范,被final修饰的常量名称,所有字母都大写。

final修饰成员变量,必须初始化,初始化有两种

  • 显示初始化;
  • 构造方法初始化。
    但是不能两个一起初始化

final和private的区别:

  1. final修饰的类可以访问;
    private不可以修饰外部类,但可以修饰内部类(其实把外部类私有化是没有意义的)。

  2. final修饰的方法不可以被子类重写;
    private修饰的方法表面上看是可以被子类重写的,其实不可以,子类是看不到父类的私有方法的。

  3. final修饰的变量只能在显示初始化或者构造函数初始化的时候赋值一次,以后不允许更改;
    private修饰的变量,也不允许直接被子类或一个包中的其它类访问或修改,但是他可以通过set和get方法对其改值和取值。

##多态

概念:

对象在不同时刻表现出来的不同状态。

多态的前提:

  • 要有继承或者实现关系。
  • 要有方法的重写。
  • 要有父类引用指向子类对象。

程序中的体现:
父类或者接口的引用指向或者接收自己的子类对象。

好处和作用:
多态的存在提高了程序的扩展性和后期可维护性。

弊端:
父类调用的时候只能调用父类里的方法,不能调用子类的特有方法,因为你并不清楚将来会有什么样的子类继承你。

多态的成员特点:

  • 成员变量:

    编译时期:看引用型变量所属的类中是否有所调用的变量;
    运行时期:也是看引用型变量所属的类是否有调用的变量。
    成员变量无论编译还是运行都看引用型变量所属的类,简单记成员变量,编译和运行都看等号左边。

  • 成员方法:

    编译时期:要查看引用变量所属的类中是否有所调用的成员;
    运行时期:要查看对象所属的类中是否有所调用的成员。如果父子出现同名的方法,会运行子类中的方法,因为方法有覆盖的特性。
    编译看左边运行看右边。

  • 静态方法:

    编译时期:看的引用型变量所属的类中是否有所调用的变量;
    运行时期:也是看引用型变量所属的类是否有调用的变量。
    编译和运行都看等号左边。

一定不能够将父类的对象转换成子类类型!

父类的引用指向子类对象,该引用可以被提升,也可以被强制转换。

多态自始至终都是子类对象在变化!

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
40
41
42
43
44
45
46
47
48
49
50
51
52
//多态向下转型和向上转型的例子,多态转型解决了多态中父类引用不能使用子类特有成员的弊端。
class PolymorphicTest2 {
public static void main(String[] args) {
Phone p1 = new Nokia(); //向上转型,类型提升
Nokia no = (Nokia)p1; //向下转型,强制将父类的引用转换成子类类型,不能将Nokia类型转成Moto或Nexus类型
no.print(); //输出结果为Phone---null---0,因为继承了父类的方法

Phone p2 = new Moto();
Moto m = (Moto)p2;
m.print(); //输出结果为Moto---yellow---1599,方法重写,子类方法覆盖父类方法

Phone p3 = new Nexus();
Nexus ne = (Nexus)p3;
ne.print();
}
}

class Phone{
String color;
int price;

public void print(){
System.out.println("Phone---" + color + "---" + price );
}
}

class Nokia extends Phone{
String color = "red";
int price = 1009;

//public void print(){
// System.out.println("Nokia---" + color + "---" + price);
//}
}

class Moto extends Phone{
String color = "yellow";
int price = 1599;

public void print(){
System.out.println("Moto---" + color + "---" + price);
}
}

class Nexus extends Phone{
String color = "black";
int price = 1999;

public void print(){
System.out.println("Nexus---" + color + "---" + price);
}
}

##抽象(abstract)

抽象就是从多个事物中将共性的,本质的内容抽象出来。

抽象类:

Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。

由来:

多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。

抽象类特点:

  1. 抽象方法一定在抽象类中;
  2. 抽象方法和抽象类都必须被abstract关键字修饰;
  3. 抽象类不可以用new创建对象,因为调用抽象方法没意义;
  4. 抽象类中的抽象方法要被使用,必须由子类复写其所有的抽象方法后,建立子类对象调用; 如果子类只覆盖了部分的抽象方法,那么该子类还是一个抽象类;
  5. 抽象类中可以有抽象方法,也可以有非抽象方法,抽象方法用于子类实例化;
  6. 如果一个类是抽象类,那么,继承它的子类,要么是抽象类,要么重写所有抽象方法。
    特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

抽象类的成员特点:

  • 成员变量:可以是变量,也可以是常量;
  • 构造方法:有构造方法;
  • 成员方法:可以是抽象方法,也可以是非抽象方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
abstract class 葵花宝典 {
public abstract void 自宫();
}

class 岳不群 extends 葵花宝典 {
public void 自宫(){
System.out.println("剪刀");
}
}

class 林平之 extends 葵花宝典{
public void 自宫(){
System.out.println("指甲刀");
}
}
class AbstractTest {
public static void main(String[] args) {
岳不群 岳 = new 岳不群();
岳.自宫();

林平之 林 = new 林平之();
林.自宫();
}
}

抽象类注意事项:

抽象类不能被实例化,为什么还有构造函数?

只要是class定义的类里面就肯定有构造函数。抽象类中的函数是给子类实例化的。

一个类没有抽象方法,为什么定义为抽象类?

不想被继承,还不想被实例化。

抽象关键字abstract不可以和哪些关键字共存?

  • final:如果方法被抽象,就需要被覆盖,而final是不可以被覆盖,所以冲突。
  • private:如果函数被私有了,子类无法直接访问,怎么覆盖呢?
  • static:不需要对象,类名就可以调用抽象方法。而调用抽象方法没有意义。

接口(interface)

接口是抽象方法和常量值的集合。从本质上讲,接口是一种特殊的抽象类,这种抽象类只包含常量和方法的定义,而没有变量和方法的实现。

格式:interface 接口名{}

接口的出现将”多继承“通过另一种形式体现出来,即”多实现“。

实现(implements)

格式:class 类名 implements 接口名 {}

特点:

  • 接口不能被实例化。
  • 一个类如果实现了接口,要么是抽象类,要么实现接口中的所有方法。

接口的成员特点:

接口中的成员修饰符是固定的!

  • 成员常量:public static final,接口里定义的变量是全局常量,而且修饰符只能是这三个关键字,都可以省略,常量名要大写。
  • 成员方法:public abstract,接口里定义的方法都是抽象的,两个修饰符关键字可省略。
  • 推荐:永远手动给出修饰符。

继承与实现的区别:

  • 类与类之间称为继承关系:因为该类无论是抽象的还是非抽象的,它的内部都可以定义非抽象方法,这个方法可以直接被子类使用,子类继承即可。只能单继承,可以多层继承。((class) )
  • 类与接口之间是实现关系:因为接口中的方法都是抽象的,必须由子类实现才可以实例化。可以单实现,也可以多实现;还可以在继承一个类的同时实现多个接口。((class) extends (class) implements (interface1,interface2…))
  • 接口与接口之间是继承关系:一个接口可以继承另一个接口,并添加新的属性和抽象方法,并且接口可以多继承。((interface) extends (interface1,interface2…))

抽象类和接口的区别:

成员变量

  • 抽象类能有变量也可以有常量
  • 接口只能有常量

成员方法

  • 抽象类可以有非抽象的方法,也可以有抽象的方法
  • 接口只能有抽象的方法

构造方法

-抽象类有构造方法
-接口没有构造方法

类与抽象类和接口的关系

  • 类与抽象类的关系是继承 extends
  • 类与接口的关系是实现 implements

接口的思想特点:

  1. 接口是对外暴露的规则;
  2. 接口是程序的功能扩展;
  3. 接口的出现降低耦合性;(实现了模块化开发,定义好规则,每个人实现自己的模块,大大提高了开发效率)
  4. 接口可以用来多实现;
  5. 多个无关的类可以实现同一个接口;
  6. 一个类可以实现多个相互直接没有关系的接口;
  7. 与继承关系类似,接口与实现类之间存在多态性。
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//运动员和教练的案例(下图是思路分析)


/*
篮球运动员和教练
乒乓球运动员和教练
现在篮球运动员和教练要出国访问,需要学习英语
请根据你所学的知识,分析出来哪些是类,哪些是抽象类,哪些是接口
*/

interface SpeakEnglish {
public abstract void speak();
}

interface GoAboard{
public abstract void aboard();
}

abstract class Person {
private String name;
private int age;

public Person(){}

public Person(String name,int age){
this.name = name;
this.age = age;
}

public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}

public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}

//吃饭
public abstract void eat();
//睡觉
public void sleep(){
System.out.println("Zzz...");
}
}
//运动员
abstract class Player extends Person {
public abstract void study();
}
//教练
abstract class Coach extends Person {
public abstract void teach();
}

//篮球运动员
class BasketballPlayer extends Player implements SpeakEnglish,GoAboard{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡腿");
}

public void study(){
System.out.println(getAge() + "岁的" + getName() + "学扣篮");
}

public void speak(){
System.out.println(getAge() + "岁的" + getName() + " Say Hello World");
}

public void aboard(){
System.out.println(getAge() + "岁的" + getName() + " Go Aboard");
}
}
//乒乓运动员
class PingPangPlayer extends Player{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡蛋");
}

public void study(){
System.out.println(getAge() + "岁的" + getName() + "学扣球");
}
}
//篮球教练
class BasketballCoach extends Coach implements SpeakEnglish {
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "啃鸡爪");
}

public void teach(){
System.out.println(getAge() + "岁的" + getName() + "教扣篮");
}

public void speak(){
System.out.println(getAge() + "岁的" + getName() + " Say Hello Java");
}

public void aboard(){
System.out.println(getAge() + "岁的" + getName() + " Go Aboard");
}
}
//乒乓球教练
class PingPangCoach extends Coach{
public void eat(){
System.out.println(getAge() + "岁的" + getName() + "吃鸡蛋皮");
}

public void teach(){
System.out.println(getAge() + "岁的" + getName() + "教扣球");
}
}
class PlayerAndCoach {
public static void main(String[] args) {
//篮球运动员
BasketballPlayer bp = new BasketballPlayer();
bp.setName("郭艾伦");
bp.setAge(33);
bp.eat();
bp.sleep();
bp.study();
bp.speak();
bp.aboard();
System.out.println("***********************");
//篮球教练
BasketballCoach bc = new BasketballCoach();
bc.setName("波波维奇");
bc.setAge(65);
bc.eat();
bc.sleep();
bc.teach();
bc.speak();
bc.aboard();
System.out.println("***********************");
/*
多态
*/

Person p = new BasketballPlayer();
p.setName("Kobe Bryant");
p.setAge(33);
p.eat();
p.sleep();
//p.study();
//p.speak();

BasketballPlayer bp2 = (BasketballPlayer)p;
bp2.study();
bp2.speak();
bp2.aboard();
System.out.println("***********************");
}
}

##内部类

将一个类定义在另一个类里面,里面的那个类就称为内部类。内部类的出现,再次打破了Java单继承的局限性。

访问特点:

  • 内部类可以直接访问外部类的成员,包括私有成员。
  • 外部类要访问内部类的成员,必须要建立内部类的对象。
    内部类分类及共性:

共性:

  • 内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
  • 内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。

成员内部类

在外部类中有成员变量和成员方法,成员内部类就是把整个一个类作为了外部类的成员;
成员内部类是定义在类中方法外的类;
创建对象的格式为:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
成员内部类之所以可以直接访问外部类的成员,那是因为内部类中都持有一个外部类对象的引用:外部类名.this;
成员内部类可以用的修饰符有final,abstract,public,private,protected,static.

静态内部类

静态内部类就是成员内部类加上静态修饰符static,定义在类中方法外。

在外部类中访问静态内部类有两种场景:

  • 在外部类中访问静态内部类中非静态成员:*外部类名.内部类名 对象名 = 外部类名.内部对象*,需要通过创建对象访问;
  • 在外部类中访问静态内部类中的静态成员:同样可以使用上面的格式进行访问,也可以直接使用外部类名.内部类名.成员。

局部内部类

局部内部类是定义在方法中的类。

  • 方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
  • 方法内部类对象不能使用该内部类所在方法的非final局部变量。

可以用于方法内部类的修饰符有final,abstract;

静态方法中的方法内部类只能访问外部的静态成员。

匿名内部类

匿名内部类是内部类的简化写法,是建立一个带内容的外部类或者接口的子类匿名对象。
前提:
内部类可以继承或实现一个外部类或者接口。
格式:
new 外部类名或者接口名(){重写方法};
通常在方法的形式参数是接口或者抽象类,并且该接口中的方法不超过三个时,可以将匿名内部类作为参数传递。

##不同修饰符修饰的内容(和内部类无关)

类 成员变量 成员方法 构造方法
private Y Y Y
默认 Y Y Y Y
protected Y Y Y
public Y Y Y Y
abstract Y Y
static Y Y Y
final Y Y Y

注意,常见规则如下:

  • 以后,所有的类都用public修饰。并且,在一个java文件中,只写一个类。
  • 以后,所有的成员变量用private修饰。
  • 以后,所有的成员方法用public修饰。
    如果是抽象类或者接口:public abstract + …
  • 以后,所有的构造方法用public修饰。
    如果类是工具类或者单例类:构造用private修饰

##四种权限修饰符

本类 同包(无关类或子类) 不同包(子类) 不同包(无关类)
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y

推荐:

  • 成员变量 private
  • 构造方法 public
  • 成员方法 public

Tomcat开机启动脚本

发表于 Jul 2 2012   |   分类于 Linux   |  

在/etc/init.d下创建脚本文件tomcat,然后赋予其执行权限:chmod +x tomcat.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/s
# Tomcat auto-star
# chkconfig:2345 90 1
# description: Auto-starts tomca
# processname: tomca
export CATALINA_HOME=/usr/local/src/tomca
export JAVA_HOME=/usr/java/jdk1.7.0_0
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:JAVA_HOME/lib/tool.ja
export PATH=$JAVA_HOME/bin:$PATH /*tomcat和jdk环境变量,根据实际情况修改*
case $1 i
start
sh $CATALINA_HOME/bin/startup.s
;
stop
sh $CATALINA_HOME/bin/shutdown.s
;
restart
sh $CATALINA_HOME/bin/shutdown.s
sh $CATALINA_HOME/bin/startup.s
;
esa
exit 0

使用命令service tomcat start/restart/stop来启动/重启/停止服务。

Java面向对象

发表于 Jun 20 2012   |   分类于 Java   |  

##什么是面向对象?

面向对象是相对面向过程而言,与面向过程一样,都是一种思想。

面向过程以函数为基础,关注实现过程,强调功能行为;

面向对象以对象为基础,关注实现结果,将功能封装近对象,强调具备了功能的对象。

面向对象是基于面向过程的。

##类和对象的关系

java中描述事物通过类的形式体现,是一个抽象的概念。

对象即是该类事物实实在在存在的个体。

类是一组相同属性行为的对象的抽象。

举例:

类 :手机

对象:Nokia,Moto,HTC

##类有哪些内容组成?

描述任意一类事物就是在描述他的属性和行为。

Java中的类class由成员变量和成员方法两部分组成,分别对应一类事物的属性和行为。
定义类其实也就是定义类中的成员(成员变量和成员方法)。

1
2
3
4
5
6
7
8
9
10
11
12
//定义一个类
class Phone{
//成员变量(属性)
String color = "white";
String brand = "Nokia";
int price = 998;

//成员方法()
public void createPhone(){
System.out.println(color + brand + price);
}
}

##变量使用原则

就近原则。

##如何创建对象?

java中通过new关键字来创建实体。实体其实就是用来封装具体数据用的,如数组。对象也是同样道理,使用new关键字来创建对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//创建一个对象
class Phone{
String color = "white";
String brand = "Nokia";
int price = 998;

public void createPhone(){
System.out.println(color + brand + price);
}
}

class PhoneDemo{
public static void main(String args){
Phone p = new Phone();//创建对象
p.color = "black";//修改对象的属性
p.createPhone();//使用对象的功能,即调用类中的方法
}
}

##成员变量与局部变量有什么区别?

作用范围

成员变量:定义在类中,可以被类中的任意方法访问。

局部变量:只在它所属的局部大括号中有效。

存储情况

成员变量(非静态):存储在堆内存中,随着对象的存在而存在。当对象变成垃圾被回收时,该该对象中的成员变量会消失。

成员变量(静态):存储在方法区中,随着类的加载而加载,随着类的消失而消失。

局部变量:存储在栈内存中,当方法被调用,或者语句被执行的时候,才存在。

当方法运行完毕,或者语句运行完毕时,局部会被自动释放。所以成员变量也称之为实例(对象)变量。

初始化情况

成员变量:在堆内存中有默认初始化值。

局部变量:必须手动初始化后,才可以被使用。

##匿名对象

匿名对象是对象的简化形式,是没有名字的对象。

匿名对象的使用注意事项:

当对对象方法仅进行一次调用的时候使用;

匿名对象可以作为实际参数进行传递。

##封装(Encapsulation)

隐藏对象的属性和实现细节,仅对外提供公共访问方式。

封装的好处:

  • 将变化隔离。
  • 便于使用。
  • 提高重用性。
  • 提高安全性。

原则:

将不需要对外提供的内容都隐藏起来。
把属性都隐藏,提供公共方法对其访问。

##private(私有)关键字

概念:

  1. 权限修饰符。
  2. 用于修饰成员(成员变量和成员方法)
  3. 被私有化的成员只在本类中有效。
  4. 当成员私有后,提高了安全性。但是访问权限降低了。这时可以通过对外提供公有方法的形式对其进行访问。

好处:

可以在方法中对成员变量的访问进行控制。

常用场景:

将成员变量私有化,对外提供对应的set ,get方法对其进行访问。提高对数据访问的安全性。

1
2
void setAge(int a){}
int getAge()

##构造方法

构造方法的特点:

构造方法的方法名必须与类名相同。

构造方法没有返回类型,也不能定义为void,在方法名前面不声明方法类型。

构造方法不能由编程人员调用,而要系统调用。

一个类可以定义多个构造方法,也就是构造方法可以重载,以参数的个数,类型,或排列顺序区分。

构造方法细节:

如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数的默认构造器,这个构造器不执行任何代码。

作用:

构造方法的主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//无参构造方法调用有参构造方法

class Test{
public static void main(String args){
Phone p = new Phone();
}
}

class Phone{
private String brand;
Phone(){//无参构造方法
this(""); //必须放在第一行,而且不能直接用this(brand)
System.out.println("这是个无参构造方法。");
}

Phone(String brand){//有参构造方法
this.brand = brand;
}
}

构造方法和一般方法的区别:

从功能上的区别:

  • 构造方法是给对象初始化的
  • 一般方法是因为对象需要满足某种功能定义的

从执行上的区别:

  • 构造方法,是对象创建的时候被执行,不用调用。
  • 一般方法是什么时候调用,就什么时候执行,不调用就永远不执行。

从书写上的区别:

  • 构造方法,是不需要有返回值,包括void,但是可以有return关键字来结束。
  • 一般方法是必须具备返回值

构造代码块:

构造代码块又叫初始化块,在创建对象时执行,构造代码块是对构造方法的补充,不接收任何参数,定义一些所有对象共有的属性和方法时就可以用构造代码块。

特点:

  1. 构造代码块在类中方法外;
  2. 构造代码块没有名字,只能在创建对象的时候被自动调用;
  3. 如果有多个构造代码块,那么创建对象时就按照构造代码块的源码顺序,依次执行,构造代码块全部执行完成后,再执行构造方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//构造代码块
class Person {
public Person(){
System.out.println("我是构造方法");
}
public Person(int a){
System.out.println("这是构造方法1");
}
{
for(int a = 1;a <= 10;a++){
System.out.println("Hello Java!");
}//定义对象共有的属性和方法,提高代码的复用性和整个应用的可维护性。
System.out.println("这是构造代码块2");
}
}

##对象初始化过程

加载main方法所在的类和对象类进方法区→执行静态代码块→主方法进栈→在栈内存中开辟一个变量空间→在堆内存中开辟内存空间new一个对象→给对象一个内存地址值→对成员变量进行默认初始化→对成员变量进程显式初始化→构造代码块对成员变量初始化→构造方法对变量初始化→把地址值赋给栈内存中的变量空间

##代码执行顺序

静态代码块→构造代码块→构造方法
静态成员随类的加载而加载,类只加载一次,因此静态代码块也只执行一次。

##this关键字

this是一个关键字。代表当前对象的引用。

哪个对象调用this所在的方法,this就代表哪个对象。

使用场景:

当局部变量和成员变量一样的时候,使用this关键字可以解决局部变量隐藏成员变量问题;

1
2
3
4
5
6
7
8
9
class Phone{
String color;
String brand;

public void show(String color,String brand){
this.color = color;
this.brand = brand;//this.成员变量名
}
}

在成员方法中调用其他成员方法,如果不加,默认也有this;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Phone{
String color;
String brand;

public void setColor(String color){
this.color = color;
}
public String getColor(){
return color;
}

public void show(){
System.out.println(this.getColor());//在成员方法中调用其他成员方法
}
}

在构造方法中调用其他的构造方法,用法是“this(参数列表)”,只能用在类的构造方法中,而且只能放在构造方法的第一行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Phone{
String color;
String brand;

public Phone(){}

public Phone(String color){
this.color = color;
}

public Phone(String color,String brand){
this("yellow"); //调用Phone(String color)这个构造方法,放在第一行
this.brand = brand;
}
}

##Static关键字

static是一个修饰符,用于修饰成员(成员变量和成员方法)。

当成员被静态修饰后,就多了一种被调用方式,不仅可以被对象调用,也可以被类名调用,格式是:类名.静态成员。

static特点:

  1. 随着类的加载而加载。也就是说:静态会随着类的消失而消失,说明它生命周期最长。
  2. 优先于对象存在。因为静态随类的加载而加载,因此一定是静态先存在,对象后存在。
  3. 被所有对象共享。对对象的共享数据在方法区提供单独的存储空间,节省内存。
  4. 可以被类名所调用。无需在堆中创建对象即可被调用。

非静态的成员变量又叫实例变量,静态变量又叫类变量。

非静态的成员变量(实例变量)与静态变量(类变量)的区别:

在内存中的位置:

  • (类变量)静态变量随着类的加载而存在于方法区中;
  • 实例变量随着对象的建立而存在于堆内存中。

生命周期:

  • 静态变量的生命周期最长,随着类的消失而消失;
  • 实例变量的生命周期随着对象的消失而消失。

所属:

静态变量也称之为类变量,所属于整个类,被整个类的对象所共享;
实例变量是对象的特有数据,所属于对象。

静态使用注意事项:

静态方法访问有局限性,只能访问静态成员,不能访问非静态成员。

  • 非静态方法既可以访问静态也可以访问非静态;
  • 非静态方法中不可以定义静态变量,因为静态随类加载而加载,优于对象存在的。

静态方法中不可以定义this,super关键字。

  • 因为静态优先于对象存在。所以静态方法中不可以出现this。

主函数是静态的。

1
2
3
4
5
6
7
8
9
10
//主函数举例
class StaticMain {
static int x = 4;
public static void main(String[] args) {
method();//主函数是静态的,要调用method方法,则method方法也必须是静态的。
}
public static void method(){
System.out.println(x);//method方法是静态的,因此使用的变量x也必须是静态的。
}
}

静态代码块:

随着类的加载而执行,只执行一次并优先于主函数。 用于给类进行初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
执行顺序:静态代码块→构造代码块→构造方法
*/

class Person {
{
System.out.println("这是构造代码块");
}
public Person(){
System.out.println("这是构造方法");
}
static{
System.out.println("这是静态代码块");
}

}
class StaticDemo4 {
public static void main(String[] args) {
new Person();
new Person();//多次调用对象,只执行一次静态代码块。
}
}

局部代码块&构造代码块&静态代码块

局部代码块:

  • 作用:控制变量的生命周期;
  • 在程序中,当我们已经使用完x后,并且在接下来的代码中,不会再用到x,那么就没必要让x在内存中占用空间了,这用情况下,可以使用局部代码块,将x及其所设计到的区域封装为局部代码块,他们在程序执行中顺序不变,只是在执行完成后消失。

构造代码块:

  • 作用:存在于类中,它可以给所有对象进行初始化;
  • 当类中的构造方法以重载的形式存在时,并且有共同成员变量或共同的方法时,可以通过构造代码块对其进行初始化;这样可以减少代码的重复。

静态代码块:

  • 作用:加载驱动器;
  • 当类中的方法都被静态了化,并且构造方法被private了,这时我们不能再将这个类实例化,然而又想让类增加一些属性,就可以使用静态代码块。

##给成员变量赋值的方式有几种?分别怎么实现?

  1. 在类中显式初始化时给成员变量赋值;
  2. 非静态的成员方法调用成员变量时给成员变量赋值;
  3. 构造方法里调用成员变量赋值;
  4. 创建对象时调用构造方法时给成员变量赋值;
  5. 类调用静态成员变量时可以给静态成员变量赋值。

tomcat日志设置规范

发表于 May 22 2012   |   分类于 Server   |  

涉及两部分:关闭控制台日志和规范程序日志大小和个数。

1.tomcat程序日志

在%TOMCAT_HOME%/conf/logging.properties中设置catalina.org.apache.juli.FileHandler.level = OFF,关闭catalina的输出。

如需保留catalina输出,可参考文档管理系统经验总结添加自动删除脚本。

2.程序日志

编辑log4j.properties文件。一般可见log4j.rootCategory=info,stdout,file,stdout输出到控制台,file输出到文件。

1)关闭控制台日志输出

将log4j.appender.stdout=org.apache.log4j.ConsoleAppender注释掉,禁止程序向catalina.out输出控制台信息。

2)规范程序日志输出

log4j.appender.file.MaxFileSize=10MB //单个日志大小

log4j.appender.file.MaxBackupIndex=10 //循环日志个数

在限定日志大小和数量情况下,可根据项目实际情况设定日志跟踪级别。

1.堆大小

普通工控机:-Xmx1g -Xms1g

高配服务器:-Xmx2g -Xms2g

初始堆值和最大堆值设置同样大小,一般不超过总内存的1/2,32bit系统下由于寻址问题一般不能超过3GB,系统中有其他重要程序(如数据库)占用内存时,要调小该值。

常见由堆大小引发的内存溢出:java.lang.OutOfMemory

2.年轻代大小

普通工控机:-Xmn512m

高配服务器:-Xmn1g

一般为堆大小的3/8-1/2

常见由年轻代大小引发的内存溢出:java.lang.OutOfMemoryError: Java heap space Heap size

3.持久代大小

普通工控机:-XX:PermSize=256m -XX:MaxPermSize=256m

高配服务器:-XX:PermSize=256m -XX:MaxPermSize=256m

初始持久代值和最大值设置同样大小,一般值不用调整,若同一tomcat下有多个服务时,可以略微增加。

常见由持久代大小引发的内存溢出:java.lang.OutOfMemoryError: PermGen space

编辑tomcat/bin/catalina.sh文件,在文件开头非备注行添加参数:

JAVA_OPTS=’参数一 参数二……’

例:

普通工控机:

JAVA_OPTS=’-Xms1g -Xmx1g -Xmn512m -XX:PermSize=256m -XX:MaxPermSize=256m’

高配服务器:

JAVA_OPTS=’-Xms2g -Xmx2g -Xmn1g -XX:PermSize=256m -XX:MaxPermSize=256m’

在不同系统和不同JDK下允许值不一样,事先需进行参数测试,如普通工控机:

java -Xms1g -Xmx1g -Xmn512m -XX:PermSize=256m -XX:MaxPermSize=256m -version

输入此命令可以正常返回版本号后,再进行修改。

修改完成后,重启tomcat,可以观察到ps aux结果中,tomcat的RSS值(实际驻留内存)大幅上升。

注意:

JDK 1.5及以前版本对内存默认串行回收,所以没有特殊情况JDK均要求升级至1.6及以上版本。

Java基础知识

发表于 Apr 13 2012   |   分类于 Java   |  

关键字

  • Java标识符

    大小写字母,数字,_和$,不能以数字开头,不能使用关键字,严格区分大小写。
    Java注释:单行注释,多行注释,文档注释;调试程序。

  • 常量与变量

    常量的分类:整数,小数,布尔,字符(单引号),字符串(双引号),null常量

    整数常量:进制。

    三个二进制位为一个八进制,四个二进制位为一个十六进制位。

    负数:正数二进制取反加1,负数二进制最高位是1.

  • 变量

    变量名,数据类型,数据。

    强类型语言。

    基本数据类型

    数值型:整数类型(byte,short,int,long);浮点型(float,double);

    字符型(char)

    布尔型(boolean)

    引用数据类型:类(class);接口(interface);数组([ ])

    整数默认:int 小数默认:double

    类型提升和强制类型转换(丢失精度),

    字符运算:编码表(ASCII)国标码(gb2312)unicode(国际标准编码表)

    隐性转换,显性转换

    +=在底层自动做强制转换。

    b=a++:先把a赋给b,b=a,a=a+1

    b=++a:a先自增,然后赋给b,a=b=a+1

    成员变量和局部变量的区别:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    1.
    成员变量定义在类中,整个类中都可以访问;
    局部变量定义在函数,语句,局部代码块中,只在所属的区域有效。
    2.
    成员变量存在于堆内存的对象中;
    局部变量存在于栈内存的方法中;
    3.
    成员变量随着对象的创建而存在,随着对象的消失而消失;
    局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
    4.
    成员变量都有默认初始化值;
    局部变量没有默认初始化值。

##运算符

  • 逻辑运算符

    与,&

    或,|

    异或,^ 两边结果不同为真,相同为假

    非,!

    短路,&&左边结果假,右边不计算

    ||左边结果真,右边不计算

  • 位运算符

    转换为二进制计算;

    一个数异或另一个数两次,结果还是这个数〈常用于加解密〉;

    << 左移 左移几位就是原数据乘以2的几次方;

    >> 右移 右移几位就是原数据除以2的几次方,高位出现的空位,原来高位是什么就用什么补这个空位,保证数据正负不变;

    >>> 无符号右移 由移后,无论高位是什么,高位出现的空位都用0来补。

  • 三元运算符
    1
    2
    3
    (条件表达式)?表达式1:表达式2    
    如果条件为true,运算后的结果是表达式1;
    如果条件为false,运算后的结果是表达式2.

流程控制

  • 判断结构

    if语句

    (1)

    1
    2
    3
    4
    if(条件表达式)    
    {
    执行语句;
    }

    if语句控制的语句为单条语句时,大括号可以省略;如果if语句后没有大括号,if就控制离它最近的那条语句。

    (2)

    1
    2
    3
    4
    5
    6
    7
    8
    if(条件表达式)
    {
    执行语句;
    }
    else
    {
    执行语句;
    }

    三元运算符就是if else的简写格式;当if else运算符,有一个具体的结果的时候,可以简写为三元运算符。

    (3)
    多条件判断

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if(条件表达式)
    {
    执行语句;
    }
    else if(条件表达式)
    {
    执行语句;
    }
    else
    {
    执行语句;
    }

    局部代码块可以定义局部变量的生命周期。

    switch语句

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    switch(表达式)//byte,int,short,char
    {
    case 取值1:
    执行语句;
    break;
    case 取值2:
    执行语句;
    break;
    ……
    default:
    执行语句;
    break;
    }

    if和switch的应用场景

    if:

    1
    2
    3
    1.对具体的值进行判断;
    2.对区间判断;
    3.对运算结果是boolean类型的表达式进行判断。

    switch:

    1
    2
    1.对具体的值进行判断;    
    2.值的个数通常是固定的;

    对于几个固定的值判断,建议使用switch语句,因为switch语句会将具体的答案都加载进内存,效率相对高一点。

  • 循环结构

    while

    1
    2
    3
    4
    while(条件表达式)
    {
    执行语句;
    }

    do while

    1
    2
    3
    4
    do
    {
    执行语句;
    }while(条件表达式);

    for

    1
    for(初始化;表达式;条件)执行语句
  • break与contunue

    break:跳出

    1
    2
    break作用的范围:switch语句或者循环语句。    
    当break语句单独存在时,下面不要定义其他语句,因为执行不到。

    continue:继续

    1
    2
    continue作用的范围:循环结构。    
    结束本次循环,继续下次循环。

    如果continue单独存在时,下面不要有任何语句,因为执行不到。

##内存的划分

  • 寄存器
  • 本地方法区
  • 方法区
  • 栈内存

    存储的都是局部变量,而且变量所属的作用域一旦结束,该变量自动释放。即栈的生命周期比较短,更新比较快.

  • 堆内存

    存储的是数组和对象(其实数组就是对象),凡是new建立的都在堆中.

    (1)每一个实体都有首地址;

    (2)堆内存中的每一个变量都有默认初始化值,根据类型的不同而不同。整数是0,小数是0.0或0.0f,boolean是false,char是’\u0000’.

##一般函数与构造函数的区别

  • 构造函数:

    对象创建时,就会调用与之对应的构造函数,对对象进行初始化;

    只调用一次。

  • 一般函数:

    对象创建后,需要函数功能时才调用;

    可以调用多次。

我的故事

发表于 Apr 4 2012   |   分类于 随笔   |  

我讲下自己的故事,我毫不讳言自己内心那点小九九,我当然渴望得到更多的同情。

不知道从什么时候开始,清明节不再是作为某些人祭祖而存在的节日了。放假三天,成群结队地到处跑着旅游,对这种有争议的做法,如果没有触及到自己的利益,我也懒得去做过多的评论。只是这某些人这种数典忘祖,只顾自己快活,不顾祖宗活死的做法,直接导致我回家乘车的难度系数增加了好多倍。由于家在登封,每逢节日,游客都会很多。那天,在车站等车去登封的有上千人,一辆车最多只能拉40人,我九点买到的是十一点十分的票。

人太多,一开始都排队还像模像样,没过多久就乱了。人挤人,成千人挤在一个大院里,由于前一天晚上我在宿舍跟同学一起打了一个晚上的DotA,困的不行,我就随着人流飘来飘去。突然我觉得有只手在摸我的口袋,因为困有点意识模糊,我只是推开了她的手,也懒得去揭穿她,只是抬头看了眼那人。我们四目相对那一瞬间,一个嘴张歪的女孩儿叫起来了。我就这样成了人所不齿的色狼……对于自己这角色的瞬间转变,显然让我措手不及,我开始辩解。“我左手提着袋子,右手拿着手机,怎么摸你屁股?”随后,我周围立马聚集了六七个歪嘴女的同伙,看装束,像是河南司法警官学校的学生。

那时候,我真是被怼蒙了,任凭那些人骂出怎样难听的话,我都毫无反应。我心里想的唯一一件事是我周围这一千多号人怎么看我,在这一千多人眼里,我就是一素质极其低下的大色狼。我怎么都想不通啊,事情怎么会变成这个样子,人生的大起大落甚至让我产生了呼吸障碍。千夫所指,不白之冤,有口莫辩,我长这么大没受过这样的冤枉,没被这么多人冤枉过……事情还没玩!那些人走了之后,我旁边有其他人聊起来,“那些人就是装逼,不就仗着人多嘛,这就随便冤枉人?”听到这句话,我的眼泪瞬间就流下来了。

那一刻,我心里没有对那个偷我东西不成反而冤枉我的女孩儿的怨恨,没有对那群肆意践踏我尊严的女孩儿朋友的怨恨,更没有对那些人知道真相而不愿帮我澄清的人的怨恨,我内心只是单纯地难受,无以复加的难受。我想不通,我想不通啊,到底是自己太天真,还是这个社会太难懂。我唯一想到的就是马上逃离那个停车场大院,再也不要看到那些人的目光,事实上我自始至终也没敢看其他人的眼。到了车上,我又想到一些感情上的事,就彻底泪崩了,整个人已经处于一种崩毁的状态。我曾经也试图说清楚感情的事,但是最终发现一切都是徒劳,所幸不说了。我就觉得特别累特别累…在那种状态下,我睡着了,梦里不知怎么就梦到了韩寒的前一天发的微博,最后一段话,张国荣的句子“我一生没做坏事,为何这样?”韩寒说他知道为什么,“因为,你一生没做坏事,所以,就是这样。”可我还是不懂啊…为什么我对别人的宽容会让别人如此的下贱凶残?为什么我面对这些下贱凶残会那么地无力?为什么这个社会会如此地纵容作恶却要无情地击溃善良?

“我向来是不惮以最坏的恶意,来推测中国人的,然而我还不料,也不信竟会下劣凶残到这地步。”一个人的本性很难改变,一个民族的本性更难。每个中国人都无法摆脱这样一个事实:也许这一刻你是韩寒、张国荣、舒淇,背负着无数人的责难,但这不是最糟糕的,最糟糕的是下一刻你就是那个下劣凶残的中国人,又或者是内心极度阴暗扭曲且丧心病狂到无可救药的方舟子。每个人都是小悦悦,每个人也都是自己口诛笔伐的十八个冷漠的路人。原来骂来骂去,我们竟然骂的都是自己。如此的悖论也许只有在我们这样神奇的国度才会出现吧。契诃夫在给朋友的信里说“要把自己身上的奴性一滴一滴挤出去”。我们不是没有这样的大师,“一个没有英雄的民族是可悲的民族,而一个拥有英雄而不知道爱戴他、拥护他的民族则更为可悲。”我们还要为那点奴性坚持到什么时候?

瞎扯这么多,我当然明白那些冤枉我的人不会有丝毫的改变,我却也不敢想象此刻作为警校学生的他们,以后真正成了所谓的“人民警察”会是怎样一个状态。此时此刻,我当然也怨恨他们,但却不是最主要的情绪,我依然觉得很迷茫。生于长于这个价值缺失的年代,我有太多的困惑。每日都活在战战兢兢之中,即便已经如履薄冰,即便已经尽最大努力避免了天灾,却还要时刻提防自己会遭遇这样那样的人祸。太累了。

1…101112…15
Ailurus

Ailurus

Android Developer

145 日志
13 分类
215 标签
RSS
Github Twitter Facebook Weibo
Links
  • 明哥
  • veaer
  • 程序亦非猿
  • 阿布
  • 区长
  • 卡老师
© 2020 Ailurus
由 Hexo 强力驱动
主题 - NexT.Pisces