第一篇:Java学习心得
Java学习心得之一——鼠标事件处理
Java中,鼠标事件一般由用户界面个组件的内部实现,用户不用关心太多细节。然而,在处理一些鼠标自适应事件如鼠标绘图、鼠标移动特定组件时,就需要对鼠标事件做专门的处理了。
和其他用户界面组件的实现一样,Java对鼠标事件的处理也是通过AWT事件处理机制来实现的,即:事件源(在此,鼠标事件的事件源可以看做隐藏,或为需要对鼠标事件响应的相关组件,如Panel对象等)注册监听器(mouseListener or mouseMotionListener)对象,并发送事件对象的对象(MouseEvent)。当事件发生时(如鼠标点击、指针移动等),事件源将事件对象传递给所注册的监听器,监听器对象利用事件对象中的信息 决定如何对事件做出响应。
在此,将引用一段源码(MouseTest.java)来具体说明。这段源码实现了如下功能:
1.绘制方块:在鼠标任意键被按下时,绘制一个正方形。
2.改变指针状态:当鼠标指针移动至图形内部时,指针变为十字形状,移出方块时,指针恢复。
3.拖动方块:当鼠标指针移至图形内部,按下任意键,拖动指针时,图形将随之移动,直到松开按钮为止。
4.擦除方块,当指针移至图形内部,双击鼠标任意键,可擦除当前方块。
具体源码如下:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import java.awt.geom.*;
public class MouseTest
{
public static void main(String[] args)
{
MouseFrame frame=new MouseFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class MouseFrame extends JFrame
{
public MouseFrame()
{
setTitle(“Mouse Test”);
setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
MousePanel panel=new MousePanel();
add(panel);
}
public static final int DEFAULT_WIDTH=500;
public static final int DEFAULT_HEIGHT=400;
}
class MousePanel extends JPanel
{
//绘制图形
public MousePanel()
{
squares=new ArrayList
current=null;
addMouseListener(new MouseHandler());
addMouseMotionListener(new MouseMotionHandler());
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2=(Graphics2D)g;
for(Rectangle2D r: squares)
{
g2.setColor(Color.blue);
g2.draw(r);
}
}
/*
* 查询当前点是否已经存在*/
public Rectangle2D find(Point2D p)
{
for(Rectangle2D r: squares)
{
if(r.contains(p))
return r;
}
return null;
}
/*
* 用当前鼠标点击的点生成图形,并存入图形数组列表,同时重画
*/
public void add(Point2D p)
{
double x=p.getX();
double y=p.getY();
current=new
Rectangle2D.Double(x-SIDE_LENGTH/2,y-SIDE_LENGTH/2,SIDE_LENGTH,SIDE_LENGTH);
squares.add(current);
repaint();
}
/*
* 删除图形
*/
public void remove(Rectangle2D s)
{
if(s==null)return;
if(s==current)current=null;
squares.remove(s);
repaint();
}
private static final int SIDE_LENGTH=20;//正方形的边长
private ArrayList
private Rectangle2D current;//当前需要绘制的方块
private class MouseHandler extends MouseAdapter
{
/*
* 当鼠标按钮被按下时,先查找当前点是否已经包含在前期图新内,* 否,则添加至数组列表
*/
public void mousePressed(MouseEvent event)
{
current=find(event.getPoint());
if(current==null)
add(event.getPoint());
}
/*
* 处理鼠标点击事件,如果当前点包含于图形之中,且鼠标连续点击两次以上,则擦除该图形。
*/
public void mouseClicked(MouseEvent event)
{
current=find(event.getPoint());
if(current!=null && event.getClickCount()>=2)
remove(current);
}
}
private class MouseMotionHandler implements MouseMotionListener
{
/*
* 改变鼠标形状
H);*/public void mouseMoved(MouseEvent event){if(find(event.getPoint())==null)setCursor(Cursor.getDefaultCursor());elsesetCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));}/** 拖动图形*/public void mouseDragged(MouseEvent event){if(current!=null){int x=event.getPoint().x;int y=event.getPoint().y;current.setFrame(x-SIDE_LENGTH/2,y-SIDE_LENGTH/2,SIDE_LENGTH,SIDE_LENGT
}}}} repaint();
第二篇:java学习心得
Java学习心得
专业:信息与计算科学班级:
姓名:学号:
日期:
河北建筑工程学院数理系
java语言产生于C++语言之后,是完全的面向对象的编程语言,充分吸取了C++语言的优点,采用了程序员所熟悉的C和C++语言的许多语法,同时又去掉了C语言中指针、内存申请和释放等影响程序健壮性的部分,可以说java语言是站在C++语言这个“巨人的肩膀上”前进的。
java采用的是相对简单的面向对象技术,去掉了运算符重载、多继承的复杂概念,而采用了单一继承、类强制转换、多线程、引用(非指针)等方式。
在java程序中不能采用地址计算的方法通过指针访问内存单元,大大减少了错误发生的可能性;而且java的数组并非用指针实现,这样就可以在检查中避免数组越界的发生。
Java语言学习要点
一、掌握静态方法和属性
静态方法和属性用于描述某一类对象群体的特征,而不是单个对象的特征。Java中大量应用了静态方法和属性,这是一个通常的技巧。但是这种技巧在很多语言中不被频繁地使用。理解静态方法和属性对于理解类与对象的关系是十分有帮助的,在大量的Java规范中,静态方法和属性被频繁使用。因此学习者应该理解静态方法和属性。Java在方法和属性的调用上是一致的,区别只表现在声明的时候,这和c++是不同的。
二、重视接口
在面向对象早期的应用中大量使用了类继承。随着软件工程理论的不断发展,人们开始意识到了继承的众多缺点,开始努力用聚合代替继承。软件工程解决扩展性的重要原则就是抽象描述,直接使用的工具就是接口。接口近年来逐渐成为Java编程方法的核心。另一方面,就应用而言,大部分开发是建立在规范基础之上的,不需要自己建立复杂的继承关系和庞大的类。因此读懂规范和用好规范已经成为应用程序开发人员的首要任务,Java各项规范的主要描述手段就是接口。
三、学好集合框架
Java描述复杂数据结构的主要方式是集合框架。Java没有指针,而是通过强大的集合框架描述数组、对象数组等复杂的数据结构。学好这些数据结构的描述方法对于应用程序编写,特别是涉及到服务器方、3层结构编程至关重要。程序员在这个时候不能再用诸如数据库结果集之类的结构描述数据了。
四、例外捕捉
Java对例外捕捉的强调是空前的,它强迫程序员用显著的与逻辑方法完全不同的方式描述例外捕捉,对于程序描述的完整性和严谨性有很大的意义。
总之学编程语言不仅仅是从理论上的学习,更重要的是要利用这门语言为你的思想服务。理解这门语言是首要的,但是要达到心领神会、融会贯通就必须勤动手,多去时间,多编一些例子。计算机科学是注重实践的学科,成功的软件开发人员无不经过大量的上机锻炼,只有理论和实践相结合才能真正掌握只是和技能。
第三篇:Java学习心得
Java学习心得
一、如何学好java??
1.就本人认为学好java关键就在于态度。态度是学习好java的前
提,积极的态度注定你就比别人学得认真,自然最终学的一定
比不认真的人学的好!
2.有良好的前提,不努力也不行的,所以呀!还得练习。要做到
常练习,多看,多思考(举一反三,多方位的,全面的使你的程序更加的完美);
3.最后一点,就是多多交流!闭门造车永远是落后的学习方式,所以好要和身边的一切可以交流技术的人积极交流,毕竟个人的力量有限的!
二、Java中那些重要知识点!(本人认为最主要的是思想,知识点也很重要,关键是在学习中总结出自己的一套思想,好的枪手都是子弹喂出来的,好的程序员都是写代
码写出来的)
1. Java数据类型
a)基本数据类型:byte、short、int、long、float、double、char、boolean(注意各自的取值范围,还有转换方式)
b)引用数据类型: 数组、类、接口。
2. 运算符号
a)算术运算符:+、-、*、/、%、++、--;
b)赋值运算符:=、+=、-=、*=、/=、%=;
c)比较运算符:<、>、=<、=>、!=;(返回值都是false/true)d)逻辑运算符:&&、||、!
e)位运算符:用于操作二进制位的运算符:<<、>>、>>>……
4.基本数据结构:
a)顺序结构
b)选择结构(if……else……,switch……case……
default……);
c)循环结构(for()、do……while、while)(分清break与
continue的用法)
5.数组(用于存储同一类型数据的一个容器)
a)表现形式:
i.ii.元素类型[] 变量名 = new 元素类型[元素的个数]; 元素类型[] 变量名 = {元素1,元素2...};(new 元素类
型[]{元素1,元素2...};)
b)数组排序方法:插入排序,二分法排序,希尔排序,还有
最主要的——冒泡排序
6.内存(1:寄存器2:本地方法区3:方法区4:栈5:堆)
a)栈(存储的都是局部变量)只要数据运算完成所在的区域
结束,该数据就会被释放。
b)堆(用于存储数组和对象,也就是实体——用于封装多个
数据的)
i.每一个实体都有内存首地址值。
ii.堆内存中的变量都有默认初始化值。因为数据类型不
同,值也不一样。
iii.垃圾回收机制
7.面向对象
a)特点:
i.ii.iii.将复杂的事情简单化。面向对象将以前的过程中的执行者,变成了指挥者。面向对象这种思想是符合现在人们思考习惯的一种思
想。
b)对事物进行属性和行为的分析
i.ii.属性:特点 行为:函数(方法)
8.访问权限
a)Private(私有的访问权限最低,只有在本类中的访问有效)
(Set方法设置,get方法提取)
b)Protected(安全的)受保护权限,体现在继承,即子类可
以访问父类受保护成员,同时相同包内的其他类也可以访问protected成员。
c)无修饰词(默认),表示包访问权限(friendly,java语言
中是没有friendly这个修饰符的,这样称呼应该是来源于
c++),同一个包内可以访问,访问权限是包级访问权限
d)public修饰词,表示成员是公开的,所有其他类都可以访
问
9.方法重载与方法重写
a)方法重载(一个类中可以有多个具有相同名字的方法,但
这些方法的参数不同(类型、个数、顺序不同))
b)方法重写(子类定义一个方法,并且这个方法的名字、返
回类型、参数的个数、参数类型与父类继承的方法完全相同)
10.java面向对象三大特性(继承,封装,多态)
a)封装(private):主要是Set方法与get方法合作应用
b)继承(extends):注意访问权限,看看是否能继承!
c)多态:父类引用或者接口的引用指向了自己的子类对象,eg(动物——1.食草动物2.食肉动物——老虎,狮子,狗);
11.抽象类与接口
a)抽象类(abstract)特点:1.不能new2.可以由抽象方法(但
是非抽象类不能有抽象方法)
b)接口(interface声明)
i.接口使用(implements):一个类可以实现一个或多个
接口,用逗号隔开。
ii.接口强调的是功能:has——a的问题!
12.多线程(Thread类与Runable接口)
a)主要方法:
i.start()启动线程
ii.iii.iv.run()程序运行的方法,功能实现区域 sleep()休眠,使程序处于休眠状态 interrupt()吵醒:吵醒处于休眠状态的程序,使进入正
常状态;
b)线程同步(synchronized锁)关键在于this与object的区别,各自使用的范围与坏境。
13.流(input/output)
a)分类:主要是字节流与字符流,还有缓冲流,数据流,对
象流……
b)方法都差不多:主要是writer()与read()还有各自对应的数
组应用!
c)出现乱码时注意你用的流是否合适以及你使用的编码格式
以否可以支持
14.套接字(Socket)
a)主要功能就是通信(安全的)(利用port进行连接)
b)利用流连接进行通信,数据传送
15.……还有好多,自己慢慢研究吧!java博大精深!
三、我们在学习中的那些难题?
1.总是遇到难以理解的东西?
2.总是以为自己回了,但是又写不出来?
3.总是觉得问题很难,但是经过别人的指点就会觉得好简
单?
第四篇:java学习心得(模版)
湖南软件职业学院
HNSERJ20080101
.湖南软件职业学院
毕 业 论 文
知识改变命运
课 题:java学习心得 院 系:软件工程系 专 业:软件技术 班 级:软件0615班 姓 名:周专书 指导老师:郑利娇 完成时间:2009-5-12
www.xiexiebang.com 软件成就未来 湖南软件职业学院
HNSERJ20080101
Java实习报告
一.引言
面临毕业与就业的压力,不久将来就要从一个学生到一个社会人的转变:技术在不断的提高,思路在不断的开阔,思想在不断的升华,更重要的是自己的理想和抱负更加的坚定。对于一个投身于IT的新人,经验谈不上,一些学习的心得倒是可以拿出来探讨一下,我们该如何面临这个似曾相识的社会,突然一天如此接近。面对“金融风暴”带来的就业压力,我们正在逐渐走向成熟,我们意志更加坚强,我们深知不经一番寒彻骨,哪来梅花扑鼻香。深深地体会到找一份好工作多么不容易的,尤其是能力匮乏的我们。一切都要付出行动,不能空想,要实现目标,就得不懈的努力。
的确,软件仍然是一个朝阳行业,对于人才的需求量也很大,这也是为什么很多人努力走上这座独木桥的原因。但是当你面临人生的一个选择时,当你决定要踏上软件开发之路时,你应该问一下自己:我为什么要选择它?其实很多人在这条道路上摸爬滚打了多年也没弄清楚这个问题的答案。如果你想在这条道路上有所成就的 话,一是兴趣使然,二是做好自己的职业规划。软件开发其实是一条非常艰苦的路,不停的学习,不断的熬夜,没有鲜花更没有掌声,陪伴你的是那漫长而孤独的夜。想一想我们准备好迎接这一切了吗?如果没有兴趣我劝你还是放弃这条路,没有兴趣你就在这条路上走不长,等待你的只有转行。如果你真的把它作为你职业生涯的跳板,那么请你做好自己的人生规划,有步骤的实现它。话题稍微远了一点,现在我就谈谈自己在Java学习方面的心得和教训。
古人云:活到老,学到老。读书学习实乃艰苦之事,花费时间,消耗精力。然苦之外亦见其乐:得到了知识,提高了认识,完善了自己。学习,求其真,务其实,应“敏而好学,不耻下问”,才能不断促使进步。学习,不仅求知,也要懂法,学会方法比掌握知识更加重要。笛卡尔说过,“没有正确的方法,即使有知识改变命运 www.xiexiebang.com 软件成就未来 湖南软件职业学院
HNSERJ20080101
眼睛的博学者也会像瞎子一样盲目摸索”,可见学习方法的重要性。
其实,大学之前几乎没有软件技术之类的概念,大三之前仍然对于程序懵懂不开。但是这并不能妨碍我热爱这个行业,也不能就断定我在这个行业里一事无成。刚学 Java,我的确感觉不开窍,特别对OO(面向对象)编程仍然不能理解。但是人如果一思考,其实什么问题都解决了。对于学习java基础的经验就是多做、多思考,基础知识的学习不能不求甚解,要追本溯源,弄清问题的本质。这样才能举一反三,由点及面。对于抽象的东西要能具体化,对于具体的东西要能抽象化。我学习java基础一直使用的是《编程思想》第四版这本书,感觉挺不错的,全面透彻通俗易懂,在国外也是广受好评,我很惋惜没有早点知道这本书,否则也不回浪费大学三年青春岁月,一无是处的打发光阴,值得庆幸的事这本书一定程度上激发了我对java学习的兴趣与潜力。英语能力强的话,可以直接看英文原版。我一直强调重视基础,如果你的java基础打的牢,你在学习那些java框架就是非常轻松的事了。
二.Java学习心得之我见
学习java,的确要学习的东西很多,就像这为朋友上面提到的那些。Java不像.net一家独大,记得在大学里教我们.net老师早就提醒过我们学java才是出路,学好java才是王道,我当时就纳闷,这不是搬石头砸自己的脚,往自己身上泼冷水吗?现在恍然大悟,他当时只是为我们指引一条明路,Java的繁盛在于开源社区的庞大,这也带来了分支太多的问题,怎样选择一条好的学习路线,对于初学者来说,的确是一件很迷茫的事。其实不管java东西再多,总有规律可循。根据自己的发展方向的不同,可以选择不同的学习路线。对于怎样成为一名出色的Java Web程序员,我的建议是:
1、JSP的知识不能欠缺,理解什么是servlet,什么是java bean,熟悉jsp常使用的标签。我自己感觉,对于JSP的学习不需要太认真,毕竟现在真正使用纯JSP的情况已经不多了,能掌握基本的知识就绰绰有余。
2、学习一个或一个以上的web表现框架。如果从使用的程度上来讲,Struts依然是最流行的框架,社会需求也很大,所以学习Struts是一个不错的选择,最近一个月我们刚刚模拟Struts开发了一个简单的网上商城,虽然算不上一大正规知识改变命运 www.xiexiebang.com 软件成就未来 湖南软件职业学院
HNSERJ20080101 的项目,总算也用到了框架,因为框架本身也是一种封装,程序开发是将简单事情复杂化,模拟Struts使我们学习三大框架和其他框架奠定良好的基础,使用框架的前提是你对他处理的业务逻辑也相当熟练了。当然也可以学习其他的框架,JSF作为一个标准,虽然现在使用的人不多,但是为了明天的主流,学习JSF也非常不错。我就是开始学习Struts,后来公司用JSF,自己又自学了JSF,其实领悟了程序设计的思想,学什么都很容易。
3、简单说说Spring,EJB。鉴于培训中心的课程安排,我们需要学习spring,spring作为业务逻辑层的轻量级架构框架spring,依然占据着主流的位置,虽然EJB3的发布对它冲击很大,但是在比较长的时 间里,它的位置还不能撼动。学习spring会很快带来实际效益。当然EJB3的发布开始渐渐挽回以前丢弃的市场,作为官方的标准,它的未来充满光明,学习EJB3会非常的有前途。自己最近也在学习EJB3其实对于刚刚毕业的学生没必要深入研究他们,很多公司也不使用这样业务逻辑层的框架,尤其是中小型企业。
4、至于xml,css这样的页面表现的东西,如果你不从事美工方面,我认为没有必要花过多的时间去学习,在平时的项目开发中慢慢的就会使用了。
还是那句话,基础很重要,永远不要忽视这一点。刚刚毕业,公司不会要求员工什么都会,只要技术扎实,学习的能力强,学习的速度就很快,企业有时候非常看重 这一点。其次掌握struts、hibernate这两个框架,达到可以熟练使用的目的,这会增加你就业的砝码。至于spring,EJB可以在以后的工作中学习使用,现在了解一下就可以了。当然作为一个java web程序员,还要了解数据库、tomcat,jboss服务器、常用的开发工具Eclipse,NetsBean等。
三,Java学习态度之我见 1.学java切忌浮躁
欲速则不达,初学者请不要被新技术迷惑,先把基础学扎实,一步一个脚印的逐步学习,不要想着一步登天。我们要如水底磐石切不可做那水上浮萍,浮躁的人永远学不到什么东西。软件开发之路是充满荆棘与挑战之路,也是充满希望知识改变命运 www.xiexiebang.com 软件成就未来 湖南软件职业学院
HNSERJ20080101
之路,没有捷径可走。梦想像《天龙八部》中虚竹一样被无崖子醍醐灌顶而轻松获得一甲子功力,是很不现实的。每天仰天大叫“天神啊,请赐给我一本葵花宝典吧”,殊不知即使你获得了葵花宝典,除了受自宫其身之苦外,你也不一定成得了“东方不败”,倒是成“西方失败”的几率高一点。“不走弯路,就是捷径”,佛经说的不无道理。
2.要有自我约束力
春来不是读书天,夏日炎炎正好眠,秋来蚊虫冬又冷,背起书包待明年。总有一些理由不学习。这样下去,我们的java之树永远长不大。古人云:“人静而后安,安而能后定,定而能后慧,慧而能后悟,悟而能后得。”很有道理。在四川大足佛教石刻艺术中,有一组大型佛雕《牧牛图》,描绘了一个牧童和牛由斗争、对抗到逐渐融合、协调,最后合而为一的故事。佛祖说:“人的心魔难伏,就像牛一样,私心杂念太多太多;修行者就要像牧童,修炼他们,驯服他们,以完美自己的人生。”我们学java也一样,要能够驯服那些影响我们学习的大牛、小牛,抵制各种诱惑,集中精力,专心学习。
3.课前稍作预习
我个人的经验和理解,课前的预习对于我们学习java尤为重要。我们课前的预习相当于第一遍的学习,而这是为第二天的学习做了一个初步的了解,而且这样学习更有效,更容易吸收课堂所学,这样既培养了我们的自学能力,也让我们发现了这个章节的难点和不懂点,上课时。在这里培训每天的理论知识量并不少,要是不预习我们会跟不上老师的教学节奏,不知其所云!
4.“三敲代码”学习法
这个词最初来自我们项目团队一个同学滑稽的演讲,班上流传的“笑柄”,但他是正确的,这是程序员都值得推荐学习的方法,为什么说是“三敲代码”呢?敲代码也并不是一味的盲敲代码。课前预习就是将课本上的实例代码敲一遍,先知识改变命运 www.xiexiebang.com 软件成就未来 湖南软件职业学院
HNSERJ20080101
不管是否理解这些代码的意思,有时候结果是很重要的,能让你豁然开朗。第二遍敲代码是课后的敲代码,老师布置的或书上的作业,虽然课后我们还是没能吸收消化当天知识,我们可以借鉴别人的代码,但一定得有自己的思路,否则只会事倍功半,适得其反。第三遍就是敲真正属于自己的代码。这是完全依靠自己所学,自主的思维,来巩固自己当日所学进行查漏补缺,那么才能保证学习效果。
5.理解+总结=记忆
认真理解和善于总结是学好java的诀窍之一。学习,就必须讲求记忆,记忆知识,就必须讲求方法。得道者事半功倍,失道者事倍功半。Java有很多知识点是需要记忆的,有的人常常感叹自己的记忆力不好,羡慕那些博闻强记的人。殊不知那些人无不是善于总结和整理自己的感官印象,才记得牢固而准确,这便是理解。列夫•托尔斯泰说:“知识,只有当它靠积极的思维得来而不是凭记忆得来的时候,才是真正的知识。”孔子云:“学而不思则罔,思而不学则殆。”这些都充分证明了这一点。知识不能只停留在书本上,必须转化为自己机能的一部分,达到“唯吾是从”。理解,必许透过现象认本质,由此及彼、由表及里,去粗取精、去伪存真。善于开动脑筋是其中的关键。
6.要善于积累
积累非常重要。庄子云:“水之积也不厚,则其负大舟也无力。风之积也不厚,则其负大翼也无力。”我们课堂上老师都会讲很多的实例,这些实例都是每个知识点的真实体现,我们都要即时的消化和理解。这样日积月累,学习效率不断提高,技术也逐步上升。有的同学认为,课堂上听不懂关系不大,课后自己看书也能认识,或者把一些问题全部留在自习课上向老师请教,„„这些想法都是错误的,这样想势必上课不求甚解,积极思考不足,既浪费了课堂时间和老师的课下时间,也变相加重自己课下的学业负担。正确的态度是:上课专心听讲,积极思考,力求当堂消化。针对课堂思路卡壳问题,我个人理解是:千万不要在课堂上寻找卡壳的原因,要求自己跳过去,听下面的内容,课下再请教老师,共同分析导致自己卡壳的原因,不失为一种较好的办法。
知识改变命运 www.xiexiebang.com 软件成就未来 湖南软件职业学院
HNSERJ20080101
在java培训中心也不定期开展职业素养的课程,尽管我觉得老师并不是那么专业,我们也抱着无所谓的态度,但是我们依然意识这就是问题的根源,通过开展职业素养,让我更深层次的认识企业文化的重要性,这也是培训中心特别的地方。人无志,不成事。提高自己的职业素养,对自身的发展会有很大的帮助。
四.职业素养的培训
1,保持积极向上乐观的心态。
积极很重要的一方面就是乐观自信。而要达到自己对自己充分的肯定,概括来说可以从四个方面来讲:第一,学会从另外一方面来看待事情,心态决定一切。第二,万事在失败前拒绝说“不行”。第三,不段给自己“充电”。“有才不怕万事难”我们要时常提高自己的内涵和修养。第四,借鉴别人的事迹,失败也是一种收获。有了职业,我们还必须得有积极和强烈的进取心,这样才能做出自己的成绩。如果没有进取心,固步自封,工作上不想精益求精,事业就没有发展的希望。我们在开始工作时,应把积累工作经验、提高工作能力作为目标,这是今后扩大自己事业空间的基础。不要计较薪金薄厚,更不能自命不凡,不屑小就。而要爱自己的职业,深思研究工作改进之术,常保进取的决心。古人说:“少壮不努力,老大徒伤悲。”进取心不但是成业的要素,并且是成己的要素。
2,注重项目团队合作。
保证一个团体生机和活力,必须使得每一个成员能够相互支持和包容,成员间充分尊重对方意见,现在终于感受到了团队合作重要性,项目小组花了一个星期做系统,除了个人知识的融会贯通,更重要的是成员的沟通与协调。有人说,一个融洽的工作环境就是成功的一半。尤其是从事软件开发,团队就是发展的根源,更是一个好的系统的前提保证,一个人的思想是有限的,多远思维交织在一起,产生的力量是不可估量的。
知识改变命运 www.xiexiebang.com 软件成就未来 湖南软件职业学院
HNSERJ20080101
3,脚踏实地的做事。
树立“职业神圣”观念。一个人对自己职业不敬,便是对这一职业的亵渎,其结果是会把事情做坏,给社会和个人带来双重损失。庄子说:“用志不分,乃凝于神。”通俗地说,敬业就是把自己从事的职业加以研究,勤勉从事的意思。做事为学,有慎心,不怕劳,不虎头蛇尾,不见异思迁。面对企业和人才之间的双向选择,一个敬业的员工无论走到哪里都将受到关注和重用,相反一个见异思迁的人在任何一个企业也不会有更光明的前途的,这是一个成为一个职业人的第一要素。我们不能“做一天和尚撞一天钟”而是应该“做一天和尚撞好一天钟”。
4,兢兢业业的工作态度。
“干一行,爱一行”——只有乐业,人才能从职业工作中得到精神享受。孔子说:“知之者不如好知者,好知者不如乐知者。”人生能从自己职业中领略出趣味,生活才有价值和意义。对于职业的态度不同,有的是以热情拥抱的态度迎接职业,有的是以冷酷无聊的态度迎接职业。其结果是,前者把职业当成是亲爱的永久伴侣,从中获益;后者则只是得到烦恼,甚至是伤痛。所以,乐业对人的一生很重要。人一生做好一件事足已,何必三心二意,一事无成。
5,做人做事要有责任心。
曾经懵懂无知,不知责任心是那般,就算今天我们依然迷茫,都说责任心是做好一件事,一份工作的保证。我们将要踏进社会,我们将会面临对工作的责任、对社会的责任、对家庭的责任,我想只有一个拥有责任心的人才能走好自己的人生旅途。古人云“一息尚存,此志不容稍懈”,“鞠躬尽瘁,死而后已”。无论什么职业,责任心、责任意识是做好工作的内在动力,记得培训中心老师曾经说过,内因决定外因,责任心是做好一件事的源动力。
知识改变命运 www.xiexiebang.com 软件成就未来 湖南软件职业学院
HNSERJ20080101
五.个人总结
人生的每一步旅途中,总有着一道难以逾越的鸿沟,对于我们不是缺少勇气,而是没有思想,惰性取代了我们原本的进取心,而我们选择了自甘堕落,碌碌无为的虚度光阴,今天之前的错误使我们选择的惩罚,在软件学院,如果只要用心去学,不说精益求精,至少可以学会谋生之道,当然不排除学院本省一些不利因素,离开软件学院,我们无从追究对与错,因为无法挽回失去的光阴,一寸光阴一寸金,寸金难买寸光阴。这次我想我会很用心的去学习!尽量把他做到完美,至少自己要九十分的满意我才会交出我培训的心得体会。
天下大事必做于细。普通人自然作一些小事,怕只怕小事也做不好,小事也做不到位。身边有很多人总不屑于做具体的事,盲目地相信“天将降大任于斯人也”。孰不知这是及其错误的心态,试着去做好自己的事实属不易。不要以为总理比村长好当。有其职斯有其责,有其责斯有其忧。如果力不及所负,才不及所任,必然祸及自身,狼狈不堪,若做错事也难辞其咎。所以用心做好身边的每一件小事,不积细流,何以成江海。所谓成功,就是在平凡中做出不平凡的坚持,而伟大就是平凡的积累。蒲老师曾经说过,做正确的事,正确的做事,在这个告诉信息化的时代,细节决定成败,方法与态度决定了效率。
“博学之,审问之,慎思之,明辩之,笃行之。” 时下,IT行业对人才的需求是很大而且持续,这更加为我梦想的实现增添了砝码,激励自己朝着梦想的云向更大的努力奋斗,只待好风凭借力,送我上青云!“少而好学,如日出之阳”,不管是现在还是将来,我们都应不断地加强学习,不断地给自己“充电”,才能开拓进取,勇于创新,不至于被社会淘汰。只要在学习的过程中保持着激情,多做多思考,再加上一颗充满梦想和远大抱负的心,我相信人人都可以成功。
知识改变命运 www.xiexiebang.com 软件成就未来
第五篇:java学习心得
Java学习心得
Java 学习杂谈
(二)鉴于上回写的一点感想大家不嫌弃,都鼓励小弟继续写下去,好 不容易等到国庆黄金周,实习总算有一个休息的阶段,于是这就开始写第二篇了。希望这次写的仍然对志同道合的朋友们有所帮助。上回讲了Java动态加载机 制、classLoader原理和关于jdk和jre三个问题。这次延续着讲一些具体的类库——
1. 关于集合框架类
相信学过 Java的各位对这个名词并不陌生,对 java.util.*这个package肯定也不陌生。不知道大家查询API的时候怎么去审视或者分析其中的一个package,每个包最重要的两个部 分就是interfaces和classes,接口代表了它能做什么,实现类则代表了它如何去做。关注实现类之前,我们应该先理解清楚它的来源接口,不管 在j2se还是j2ee中,都应该是这样。那么我们先看这三个接口:List、Set、Map。
也许有些人不太熟悉这三个名字,但相信大部分人都 熟悉ArrayList,LinkedList,TreeSet,HashSet,HashMap,Hashtable等实现类的名字。它们的区别也是满容易理解的,List放可以重复的对象集合,Set放不可重复的对象组合,而Map则放
到底Vector和ArrayList,Hashtable和HashMap有什么区别?
很多面试官喜欢问这个问题,其实更专业一点应该这样问:新集合框架和旧集合框架有哪些区别?新集合框架大家可以在这些包中找since jdk1.2的,之前的如vector和Hashtable都是旧的集合框架包括的类。那么区别是?
a.新集合框架的命名更加科学合理。例如List下的ArrayList和LinkedList b.新集合框架下全部都是非线程安全的。建议去jdk里面包含的源代码里面自己去亲自看看vector和ArrayList的区别吧。当然如果是jdk5.0之后的会比较难看一点,因为又加入了泛型的语法,类似c++的template语法。
那么大家是否想过为什么要从旧集合框架默认全部加锁防止多线程访问更新到新集合框架全部取消锁,默认方式支持多线程?(当然需要的时候可以使用collections的静态方法加锁达到线程安全)笔 者的观点是任何技术的发展都未必是遵循它们的初衷的,很多重大改变是受到客观环境的影响的。大家知道Java的初衷是为什么而开发的麽?是为嵌入式程序开 发的。记得上一篇讲到classLoader机制麽?那正是为了节约嵌入式开发环境下内存而设计的。而走到今天,Java成了人们心中为互联网诞生的语 言。互联网意味着什么?多线程是必然的趋势。客观环境在变,Java技术也随着飞速发展,导致越来越脱离它的初衷。据说Sun公司其实主打的是J2se,结果又是由于客观环境影响,J2se几乎遗忘,留在大家谈论焦点的一直是j2ee。
技术的细节这里就不多说了,只有用了才能真正理解。解释这些正是为了帮助大家理解正在学的和将要学的任何技术。之后讲j2ee的时候还会再讨论。
多 扯句题外话:几十年前的IT巨人是IBM,Mainframe市场无人可比。微软如何打败IBM?正是由于硬件飞速发展,对个人PC的需求这个客观环境,让微软通过OS称为了第二个巨人。下一个打败微软的呢?Google。如何做到的?如果微软并不和IBM争大型机,Google借着互联网飞速发展这个客 观环境作为决定性因素,避开跟微软争OS,而是走搜索引擎这条路,称为第3个巨人。那么第4个巨人是谁呢?很多专家预言将在亚洲或者中国出现,Whatever,客观环境变化趋势才是决定大方向的关键。当然笔者也希望会出现在中国,^_^~~
2. 关于Java设计模式
身边的很多在看GOF的23种设计模式,似乎学习它无论在学校还是在职场,都成了一种流行风气。我不想列举解释这23种Design Pattern,我写这些的初衷一直都是谈自己的经历和看法,希望能帮助大家理解。
首 先我觉得设计模式只是对一类问题的一种通用解决办法,只要是面向对象的编程预言都可以用得上这23种。理解它们最好的方法就是亲自去写每一种,哪怕是一个 简单的应用就足够了。如果代码实现也记不住的话,记忆它们对应的UML图会是一个比较好的办法,当然前提是必须了解UML。
同时最好能利用 Java自身的类库帮助记忆,例如比较常用的观察者模式,在java.util.*有现成的Observer接口和Observable这个实现类,看看 源代码相信就足够理解观察者模式了。再比如装饰器模式,大家只要写几个关于java.io.*的程序就可以完全理解什么是装饰器模式了。有很多人觉得刚入 门的时候不该接触设计模式,比如图灵设计丛书系列很出名的那本《Java设计模式》,作者: Steven John Metsker,大部分例子老实说令现在的我也很迷惑。但我仍然不同意入门跟学习设计模式有任何冲突,只是我们需要知道每种模式的概念的和典型的应用,这 样我们在第一次编写 FileOutputStream、BufferedReader、PrintWriter的时候就能感觉到原来设计模式离我们如此之近,而且并不是多么 神秘的东西。
另外,在学习某些模式的同时,反而更能帮助我们理解java类库的某些特点。例如当你编写原型(Prototype)模式的 时候,你必须了解的是 java.lang.Cloneable这个接口和所有类的基类Object的clone()这个方法。即深copy和浅copy的区别:
Object.clone()默认实现的是浅copy,也就是复制一份对象拷贝,但如果对象包含其他对象的引用,不会复制引用,所以原对象和拷贝共用那个引用的对象。
深 copy当然就是包括对象的引用都一起复制啦。这样原对象和拷贝对象,都分别拥有一份引用对象。如果要实现深copy就必须首先实现 java.lang.Cloneable接口,然后重写clone()方法。因为在Object中的clone()方法是protected签名的,而 Cloneable接口的作用就是把protected放大到public,这样clone()才能被重写。
那么又有个问题了?如果引用 的对象又引用了其他对象呢?这样一直判断并复制下去,是不是显得很麻烦?曾经有位前辈告诉我的方法是重写clone方法的时候直接把原对象序列化到磁盘上 再反序列化回来,这样不用判断就可以得到一个深copy的结果。如果大家不了解序列化的作法建议看一看 ObjectOutputStream和ObjectInputStream
归根结底,模式只是思想上的东西,把它当成前人总结的经验其 实一点都不为过。鼓励大家动手自己去写,例如代理模式,可以简单的写一个Child类,Adult类。Child要买任何东西由Adult来代理实现。简单来说就是Adult里的buy()内部实际调用的是Child的buy(),可是暴露 在main函数的却是Adult.buy()。这样一个简单的程序就足够理解代理模式的基本含义了。Java 杂谈
(三)这已经笔者写的第三篇Java杂记了,庆幸前两篇一直得到论坛朋友们的支持鼓励,还望大家继续指正不足之处。笔者也一直渴望通过这样方式清醒的自审,来寻找自己技术上的不足之处,希望和共同爱好Java的同仁们一起提高。
前两次分别讲述了关于jvm、jdk、jre、collection、classLoader和一些Design Pattern的自我理解。这次仍然不准备开始过渡到j2ee中,因为觉得还有一些琐碎的j2se的问题没有总结完毕。
1. 关于Object类理解
大家都知道Object是所有Java类的基类,意味着所有的Java类都会继承了Object的11个方法。建议大家去看看Object的 11个成员函数的源代码,就会知道默认的实现方式。比如equals方法,默认实现就是用“==”来比较,即直接比较内存地址,返回true 或者 false。而toString()方法,返回的串组成方式是——
“getClass().getName()+ ”@“ + Integer.toHexString(hashCode())” 其实不用我过多的解释,大家都能看懂这个串的组成。接下来再看看hashCode():
public native int hashCode();
由于是native方法,跟OS的处理方式相关,源代码里仅仅有一个声明罢了。我们有兴趣的话完全可以去深究它的hashCode到底是由OS怎么样产生 的呢?但笔者建议最重要的还是先记住使用它的几条原则吧!首先如果equals()方法相同的对象具有相通的hashCode,但equals()对象不相通的时候并不保证hashCode()方法返回不同的整数。而且下一次运行同一个程序,同一个对象未必还是当初的那个hashCode()哦。
其余的方法呢?nofigy()、notifyAll()、clone()、wait()都是native方法的,说明依赖于操作系统的实现。最后一个有 趣的方法是finalize(),类似C++的析构函数,签名是protected,证明只有继承扩展了才能使用,方法体是空的,默示什么也不做。它的作 用据笔者的了解仅仅是通知JVM此对象不再使用,随时可以被销毁,而实际的销毁权还是在于虚拟机手上。那么它真的什么也不做麽?未必,实际上如果是线程对 象它会导致在一定范围内该线程的优先级别提高,导致更快的被销毁来节约内存提高性能。其实从常理来说,我们也可以大概这样猜测出jvm做法的目的。
2. 关于重载hashCode()与Collection框架的关系
笔 者曾经听一位搞Java培训多年的前辈说在他看来hashCode方法没有任何意义,仅仅是为了配合证明具有同样的hashCode会导致equals 方法相等而存在的。连有的前辈都犯这样的错误,其实说明它还是满容易被忽略的。那么hashCode()方法到底做什么用?
学过数据结构的课程大家都会知道有一种结构叫hash table,目的是通过给每个对象分配一个唯一的索引来提高查询的效率。那么Java也不会肆意扭曲改变这个概念,所以hashCode唯一的作用就是为 支持数据结构中的哈希表结构而存在的,换句话说,也就是只有用到集合框架的 Hashtable、HashMap、HashSet的时候,才需要重载hashCode()方法,这样才能使得我们能人为的去控制在哈希结构中索引是否相等。笔者举一个例子:
曾经为了写一个求解类程序,需要随机列出1,2,3,4组成的不同排列组合,所以笔者写了一个数组类用int[]来存组合结果,然后把随机产生的组合加入 一个HashSet中,就是想利用HashSet不包括重复元素的特点。可是HashSet怎么判断是不是重复的元素呢?当然是通过
hashCode()返回的结果是否相等来判断啦,可做一下这个实验:
int[] A = {1,2,3,4};int[] B = {1,2,3,4};System.out.println(A.hashCode());System.out.println(B.hashCode());这明明是同一种组合,却是不同的hashCode,加入Set的时候会被当成不同的对象。这个时候我们就需要自己来重写hashCode()方法了,如何 写呢?其实也是基于原始的hashCode(),毕竟那是操作系统的实现,找到相通对象唯一的标识,实现方式很多,笔者的实现方式是:
首先重写了toString()方法: return A[0]“+” A[1]“+” A[2]“+” A[3];//显示上比较直观
然后利用toString()来计算hashCode():
return this.toString().hashCode();
这样上述A和B返回的就都是”1234”,在测试toString().hashCode(),由于String在内存中的副本是一样的,”1234”.hashCode()返回的一定是相同的结果。
说到这,相信大家能理解得比我更好,今后千万不要再误解hashCode()方法的作用。
3. 关于Class类的成员函数与Java反射机制
很早刚接触Java就听很多老师说过Java的动态运行时机制、反射机制等。确实它们都是Java的显著特点,运行时加载笔者在第一篇介绍过了,现在想讲 讲反射机制。在Java中,主要是通过java.lang包中的Class类和Method类来实现内存反射机制的。
熟悉C++的人一定知道下面这样在C++中是做不到的: 运行时以字符串参数传递一个类名,就可以得到这个类的所有信息,包括它所有的方法,和方法的详细信息。还可以实例化一个对象,并通过查到的方法名来调用该 对象的任何方法。这是因为Java的类在内存中除了C++中也有的静态动态数据区之外,还包括一份对类自身的描述,也正是通过这描述中的信息,才能帮助我 们才运行时读取里面的内容,得到需要加载目标类的所有信息,从而实现反射机制。大家有没有想过当我们需要得到一个JavaBean的实例的时候,怎么知道 它有哪些属性呢?再明显简单不过的例子就是自己写一个JavaBean的解析器:
a.通过Class.forName(“Bean的类名”)得到Class对象,例如叫ABeanClass b.通过ABeanClass的getMethods()方法,得到Method[]对象
c.按照规范所有get方法名后的单词就代表着该Bean的一个属性
d.当已经知道一个方法名,可以调用newInstance()得到一个实例,然后通过invoke()方法将方法的名字和方法需要用的参数传递进去,就可以动态调用此方法。
当然还有更复杂的应用,这里就不赘述,大家可以参考Class类和Method类的方法。
4. 坦言Synchronize的本质
Synchronize大家都知道是同步、加锁的意思,其实它的本质远没有大家想得那么复杂。声明Synchronize的方法被调用的时候,锁其实是加 载对象上,当然如果是静态类则是加在类上的锁,调用结束锁被解除。它的实现原理很简单,仅仅是不让第二把锁再次被加在同一个对象或类上,仅此而已。一个简 单的例子足以说明问题:
class A{ synchronized void f(){} void g(){} }
当A的一个对象a被第一个线程调用其f()方法的时候,第二个线程不能调用a的synchronized方法例如f(),因为那是在试图在对象上加第二把锁。但调用g()却是可以的,因为并没有在同一对象上加两把锁的行为产生。
这样大家能理解了麽?明白它的原理能更好的帮助大家设计同步机制,不要滥用加锁。
PS:下篇笔者计划开始对J2ee接触到的各个方面来进行总结,谈谈自己的经验和想法。希望大家还能一如既往的支持笔者写下去,指正不足之处。
Java杂谈
(四)不知不觉已经写到第四篇了,论坛里面不断的有朋友鼓励我写下去。坚持自己的作风,把一切迷惑不容易理清楚的知识讲出来,讲到大家都能听懂,那么自己就真的 懂了。最近在公司实习的时候Trainer跟我讲了很多经典事迹,对还未毕业的我来说是笔不小的财富,我自己的信念是:人在逆境中成长的速度要远远快过顺 境中,这样来看一切都能欣然接受了。
好了,闲话不说了,第三篇讲的是反射机制集合框架之类的,这次打算讲讲自己对反序列化和多线程的理解。希望能对大家学习Java起到帮助——
1.关于序列化和反序列化
应该大家都大概知道Java中序列化和反序列化的意思,序列化就是把一个Java对象转换成二进制进行磁盘上传输或者网络流的传输,反序列化的意思就是把 这个接受到的二进制流重新组装成原来的对象逆过程。它们在Java中分别是通过ObjectInputStream和
ObjectInputStream这两个类来实现的(以下分别用ois和oos来简称)。
oos的writeObject()方法用来执行序列化的过程,ois的readObject()用来执行反序列化的过程,在传输二进制流之前,需要讲这 两个高层流对象连接到同一个Channel上,这个Channel可以是磁盘文件,也可以是socket底层流。所以无论用哪种方式,底层流对象都是以构 造函数参数的形式传递进oos和ois这两个高层流,连接完毕了才可以进行二进制数据传输的。例子:
可以是文件流通道
file = new File(“C:/data.dat”);
oos = new ObjectOutputStream(new FileOutputStream(file));ois = new ObjectInputStream(new FileInputStream(file));
或者网络流通道
oos = new ObjectOutputStream(socket.getOutputStream());ois = new ObjectInputStream(socket.getInputStream());
不知道大家是否注意到oos总是在ois之前定义,这里不希望大家误解这个顺序是固定的么?回答是否定的,那么有顺序要求么?回答是肯定的。原则是什么呢?
原 则是互相对接的输入/输出流之间必须是output流先初始化然后再input流初始化,否则就会抛异常。大家肯定会问为什么?只要稍微看一看这两个类的 源代码文件就大概知道了,output流的任务很简单,只要把对象转换成二进制往通道中写就可以了,但input流需要做很多准备工作来接受并最终重组这 个Object,所以ObjectInputStream的构造函数中就需要用到output初始化发送过来的header信息,这个方法叫做 readStreamHeader(),它将会去读两个Short值用于决定用多大的缓存来存放通道发送过来的二进制流,这个缓存的size因jre的版 本不同是不一样的。所以output如果不先初始化,input的构造函数首先就无法正确运行。
对于上面两个例子,第一个顺序是严格的,第二个因为oos和ois连接的已经不是对方了,而是socket另外一端的流,需要严格按照另外一方对接的output流先于对接的input流打开才能顺利运行。
这个writeObject和readObject本身就是线程安全的,传输过程中是不允许被并发访问的。所以对象能一个一个接连不断的传过来,有很多人 在运行的时候会碰到EOFException, 然后百思不得其解,去各种论坛问解决方案。其实笔者这里想说,这个异常不是必须声明的,也就是说它虽然是异常,但其实是正常运行结束的标志。EOF表示读 到了文件尾,发送结束自然连接也就断开了。如果这影响到了你程序的正确性的话,请各位静下心来看看自己程序的业务逻辑,而不要把注意力狭隘的聚集在发送和 接受的方法上。因为笔者也被这样的bug困扰了1整天,被很多论坛的帖子误解了很多次最后得出的教训。如果在while循环中去readObject,本 质上是没有问题的,有对象数据来就会读,没有就自动阻塞。那么抛出EOFException一定是因为连接断了还在继续read,什么原因导致连接断了 呢?一定是业务逻辑哪里存在错误,比如NullPoint、ClassCaseException、ArrayOutofBound,即使程序较大也没关系,最多只要单步调适一次就能很快发现bug并且解决它。
难怪一位程序大师说过:解决问题90%靠经验,5%靠技术,剩下5%靠运气!真是金玉良言,笔者大概查阅过不下30篇讨论在while循环中使用 readObject抛出EOFExceptionde 的帖子,大家都盲目的去关注解释这个名词、反序列化的行为或反对这样写而没有一个人认为EOF是正确的行为,它其实很老实的在做它的事情。为什么大家都忽 略了真正出错误的地方呢?两个字,经验!
2.关于Java的多线程编程
关于Java的线程,初学或者接触不深的大概也能知道一些基本概念,同时又会很迷惑线程到底是怎么回事?如果有人认为自己已经懂了不妨来回答下面的问题:
a.A对象实现Runnable接口,A.start()运行后所谓的线程对象是谁?是A么?
b.线程的wait()、notify()方法到底是做什么时候用的,什么时候用?
c.为什么线程的suspend方法会被标注过时,不推荐再使用,线程还能挂起么?
d.为了同步我们会对线程方法声明Synchronized来加锁在对象上,那么如果父类的f()方法加了Synchronized,子类重写f()方法必须 也加Synchronized么?如果子类的f()方法重写时声明Synchronized并调用super.f(),那么子类对象上到底有几把锁呢?会 因为竞争产生死锁么?
呵呵,各位能回答上来几道呢?如果这些都能答上来,说明对线程的概念还是满清晰的,虽说还远远不能算精通。笔者这里一一做回答,碍于篇幅的原因,笔者尽量说得简介一点,如果大家有疑惑的欢迎一起讨论。
首先第一点,线程跟对象完全是两回事,虽然我们也常说线程对象。但当你用run()和start()来启动一个线程之后,线程其实跟这个继承了 Thread或实现了Runnable的对象已经没有关系了,对象只能算内存中可用资源而对象的方法只能算内存正文区可以执行的代码段而已。既然是资源和 代码段,另外一个线程当然也可以去访问,main函数执行就至少会启动两个线程,一个我们称之为主线程,还一个是垃圾收集器的线程,主线程结束就意味着程 序结束,可垃圾收集器线程很可能正在工作。
第二点,wait()和sleep()类似,都是让线程处于阻塞状态暂停一段时间,不同之处在于wait会释放当前线程占有的所有的锁,而 sleep不会。我们知道获得锁的唯一方法是进入了Synchronized保护代码段,所以大家会发现只有Synchronized方法中才会出现 wait,直接写会给警告没有获得当前对象的锁。所以notify跟wait配合使用,notify会重新把锁还给阻塞的线程重而使其继续执行,当有多个 对象wait了,notify不能确定唤醒哪一个,必经锁只有一把,所以一般用notifyAll()来让它们自己根据优先级等竞争那唯一的一把锁,竞争 到的线程执行,其他线程只要继续wait。
从前Java允许在一个线程之外把线程挂起,即调用suspend方法,这样的操作是极不安全的。根据面向对象的思想每个对象必须对自己的行为负责,而对 自己的权力进行封装。如果任何外步对象都能使线程被挂起而阻塞的话,程序往往会出现混乱导致崩溃,所以这样的方法自然是被毙掉了啦。
最后一个问题比较有意思,首先回答的是子类重写f()方法可以加Synchronized也可以不加,如果加了而且还内部调用了super.f()的话理论上是应该对同一对象加两把锁的,因为每次调用Synchronized方法都要加一把,调用子类的f首先就加了一把,进入方法内部调用父类的
f又要加一把,加两把不是互斥的么?那么调父类f加锁不就必须永远等待已经加的锁释放而造成死锁么?实际上是不会的,这个机制叫重进入,当父类的f方法试 图在本对象上再加一把锁的时候,因为当前线程拥有这个对象的锁,也可以理解为开启它的钥匙,所以同一个线程在同一对象上还没释放之前加第二次锁是不会出问 题的,这个锁其实根本就没有加,它有了钥匙,不管加几把还是可以进入锁保护的代码段,畅通无阻,所以叫重进入,我们可以简单认为第二把锁没有加上去。
总而言之,Synchronized的本质是不让其他线程在同一对象上再加一把锁。
Java杂谈
(五)本来预计J2se只讲了第四篇就收尾了,可是版主厚爱把帖子置顶长期让大家浏览让小弟倍感责任重大,务必追求最到更好,所以关于J2se一些没有提到的部 分,决定再写几篇把常用的部分经验全部写出来供大家讨论切磋。这一篇准备讲一讲Xml解析包和Java Swing,然后下一篇再讲java.security包关于Java沙箱安全机制和RMI机制,再进入J2ee的部分,暂时就做这样的计划了。如果由于 实习繁忙更新稍微慢了一些,希望各位见谅!
1. Java关于XML的解析
相信大家对XML都不陌生,含义是可扩展标记语言。本身它也就是一个数据的载体以树状表现形式出现。后来慢慢的数据变成了信息,区别是信息可以包括可变的 状态从而针对程序硬编码的做法变革为针对统一接口硬编码而可变状态作为信息进入了XML中存储。这样改变状态实现扩展的唯一工作是在XML中添加一段文本 信息就可以了,代码不需要改动也不需要重新编译。这个灵活性是XML诞生时候谁也没想到的。
当然,如果接口要能提取XML中配置的信息就需要程序能解析规范的XML文件,Java中当然要提高包对这个行为进行有利支持。笔者打算讲到的两个包是 org.w3c.dom和javax.xml.parsers和。(大家可以浏览一下这些包中间的接口和类定义)
Javax.xml.parsers包很简单,没有接口,两个工厂配两个解析器。显然解析XML是有两种方式的:DOM解析和SAX解析。本质上并没有谁好谁不好,只是实现的思想不一样罢了。给一个XML文件的例子:
A Cat
所谓DOM解析的思路是把整个树状图存入内存中,需要那个节点只需要在树上搜索就可以读到节点的属性,内容等,这样的好处是所有节点皆在内存可以反复搜索重复使用,缺点是需要消耗相应的内存空间。
自然SAX解析的思路就是为了克服DOM的缺点,以事件触发为基本思路,顺序的搜索下来,碰到了Element之前触发什么事件,碰到之后做什么动作。由 于需要自己来写触发事件的处理方案,所以需要借助另外一个自定义的Handler,处于org.xml.sax.helpers包中。它的优点当然是不用 整个包都读入内存,缺点也是只能顺序搜索,走完一遍就得重来。
大家很容易就能猜到,接触到的J2ee框架用的是哪一种,显然是DOM。因为类似Struts,Hibernate框架配置文件毕竟是很小的一部分配置信 息,而且需要频繁搜索来读取,当然会采用DOM方式(其实SAX内部也是用DOM采用的结构来存储节点信息的)。现在无论用什么框架,还真难发现使用 SAX来解析XML的技术了,如果哪位仁兄知道,请让笔者也学习学习。
既然解析方式有了,那么就需要有解析的存储位置。不知道大家是否发现org.w3c.dom这个包是没有实现类全部都是接口的。这里笔者想说一下Java 如何对XML解析是Jdk应该考虑的事,是它的责任。而w3c组织是维护定义XML标准的组织,所以一个XML结构是怎么样的由w3c说了算,它不关心 Java如何去实现,于是乎规定了所有XML存储的结构应该遵循的规则,这就是org.w3c.dom里全部的接口目的所在。在笔者看来,简单理解接口的 概念就是实现者必须遵守的原则。
整个XML对应的结构叫Document、子元素对应的叫做Element、还有节点相关的Node、NodeList、Text、Entity、CharacterData、CDATASection等接口,它们都可以在XML的语法中间找到相对应的含义。由于这里不是讲解XML基本语法,就不多 介绍了。如果大家感兴趣,笔者也可以专门写一篇关于XML的语法规则帖与大家分享一下。
2. Java Swing
Swing是一个让人又爱又恨的东西,可爱之处在于上手很容易,较AWT比起来Swing提供的界面功能更加强大,可恨之处在于编复杂的界面工作量实在是 巨大。笔者写过超过3000行的Swing界面,感觉用户体验还不是那么优秀。最近又写过超过6000行的,由于功能模块多了,整体效果还只是一般般。体 会最深的就一个字:累!所以大家现在都陆续不怎么用Swing在真正开发的项目上了,太多界面技术可以取代它了。笔者去写也是迫于无奈组里面大家都没写过,我不入地域谁入?
尽管Swing慢慢的在被人忽略,特别是随着B/S慢慢的在淹没C/S,笔者倒是很愿意站出来为Swing正身。每一项技术的掌握绝不是为了流行时尚跟 风。真正喜欢Java的朋友们还是应该好好体会一下Swing,相信在校的很多学生也很多在学习它。很可能从Jdk 1.1、1.2走过来的很多大学老师可能是最不熟悉它的。
Swing提供了一组轻组件统称为JComponent,它们与AWT组件的最大区 别是JComponent全部都是Container,而Container的特点是里面可以装载别的组件。在Swing组件中无论是JButton、JLabel、JPanel、JList等都可以再装入任何其他组件。好处是程序员可以对Swing组件实现“再开发”,针对特定需求构建自己的按钮、标 签、画板、列表之类的特定组件。
有轻自然就有重,那么轻组件和重组件区别是?重组件表现出来的形态因操作系统不同而异,轻组件是Swing自己提供GUI,在跨平台的时候最大程度的保持一致。
那么在编程的时候要注意一些什么呢?笔者谈谈自己的几点经验:
a.明确一个概念,只有Frame组件才可以单独显示的,也许有人会说JOptionPane里面的静态方法就实现了单独窗口出现,但追寻源代码会发现其实现 实出来的Dialog也需要依托一个Frame窗体,如果没有指定就会默认产生一个然后装载这个Dialog显示出来。
b.JFrame是由这么几部分组成:
最底下一层JRootPane,上面是glassPane(一个JPanel)和layeredPane(一个JLayeredPane),而layeredPane又由contentPane(一个JPanel)和menuBar构成。我们的组件都是加在
contentPane上,而背景图片只能加在layeredPane上面。至于glassPane是一个透明的覆盖了contentPane的一层,在特定效果中将被利用到来记录鼠标坐标或掩饰组件。
c.为了增强用户体验,我们会在一些按钮上添加快捷键,但Swing里面通常只能识别键盘的Alt键,要加入其他的快捷键,必须自己实现一个ActionListener。
d.通过setLayout(null)可以使得所有组件以setBounds()的四个参数来精确定位各自的大小、位置,但不推荐使用,因为好的编程风格不 应该在Swing代码中硬编码具体数字,所有的数字应该以常数的形式统一存在一个静态无实例资源类文件中。这个静态无实例类统一负责Swing界面的风 格,包括字体和颜色都应该包括进去。
e.好的界面设计有一条Golden Rule: 用户不用任何手册通过少数尝试就能学会使用软件。所以尽量把按钮以菜单的形式(不管是右键菜单还是窗体自带顶部菜单)呈现给顾客,除非是频繁点击的按钮才有必要直接呈现在界面中。
其实Swing的功能是相当强大的,只是现在应用不广泛,专门去研究大概是要花不少时间的。笔者在各网站论坛浏览关于Swing的技巧文章还是比较可信 的,自己所学非常有限,各人体会对Swing各个组件的掌握就是一个实践积累的过程。笔者只用到过以上这些,所以只能谈谈部分想法,还望大家见谅!