Tại sao Java được coi là dễ mang theo hơn các ngôn ngữ khác như C ++?


16

Điều gì khác nhau giữa "viết một JRE cụ thể cho từng nền tảng" cho các nhà phát triển Java và "viết một trình biên dịch C ++ cho mỗi nền tảng" cho các nền tảng C ++?

Câu trả lời:


33

Java được biên dịch một lần chạy ở bất cứ đâu. C ++ được viết một lần biên dịch ở bất cứ đâu.


3
Chà, rõ ràng là bạn chưa có nhiều kinh nghiệm về phát triển GUI. (Đang chờ Qt ...)

27
Bất cứ ai tuyên bố rằng C ++ là "viết một lần biên dịch ở bất cứ đâu" chưa bao giờ phải chuyển một chương trình C ++ ...
BlueRaja - Danny Pflughoeft

7
Tôi đồng ý với BlueRaja. Chuyển một chương trình C ++ có nghĩa là nhiều hơn so với chuyển trình biên dịch. C ++ hiện diện rộng rãi nhất trong các môi trường quan trọng, nơi những thứ như kích thước của int hoặc việc thực hiện một hệ thống tệp có thể tạo ra sự khác biệt lớn như vậy. Chuyển không chỉ đơn giản là biên dịch lại.
rahmu

8
@ Pubby8 không, các vấn đề về tính di động cũng xuất phát từ mã khá chuẩn tạo ra các giả định không thể truy cập được , như các giả định về tính cuối cùng (mà bạn, bạn cũng có thể mắc phải trong Java), căn chỉnh và các loại cơ bản của sizeof.
R. Martinho Fernandes

5
Viết một lần, gỡ lỗi ở mọi nơi.
bhagyas

25

"Viết một JRE cụ thể cho từng nền tảng" không phải là việc bạn làm mọi lúc. Chuyển JRE sang một nền tảng mới là điều bạn chỉ cần làm một lần. Nhiệm vụ này thường được thực hiện bởi nhà bảo trì / nhà phát triển cốt lõi của chương trình và / hoặc nền tảng. Rất nhiều yếu tố có thể xuất hiện khi quyết định JRE sẽ được chuyển đến ai và như thế nào. Trong số những thứ khác, nó phụ thuộc vào bản quyền được cấp phép được xuất bản theo (Tôi nghe Java là Nguồn mở, vì vậy tôi đoán bất cứ ai cũng có thể làm được). Giai thoại vui, Steve Jobs đã đưa ra một vấn đề lớn về việc không muốn chăm sóc việc chuyển Java trên Mac , khoảng một năm trước.

Vấn đề không phải là làm thế nào hoặc ai chuyển JRE, mà thực tế là một khi nó được chuyển, mọi ứng dụng Java bây giờ về mặt lý thuyết sẽ dễ dàng chạy trên máy mới. Theo nghĩa đó, JRE tạo thành một lớp trừu tượng, ẩn hoàn toàn máy, cho phép chuyển dễ dàng.

Tuy nhiên, thực tế không phải lúc nào cũng đẹp như thế này. Tôi sẽ không đi xa đến mức gọi tính di động là "huyền thoại", nhưng sự thật là nó không quá hoàn hảo. Chẳng hạn, Java có một gói được gọi là JNIcho phép gửi các cuộc gọi riêng, bỏ qua JRE, do đó ngăn chặn tính di động liền mạch hoàn hảo, điều mà người hâm mộ Java muốn gọi là "Viết một lần chạy ở mọi nơi".

Như đã đề cập trong các bình luận, cách tiếp cận tính di động của C ++ là khác nhau. Một mặt, đó là một ngôn ngữ được biên dịch và các nhị phân đó hầu như luôn luôn là nền tảng cụ thể. Vì vậy, các tệp thực thi c ++ sẽ không bao giờ có thể mang theo được (không giống như Java). Mặt khác, porting trình biên dịch đôi khi có thể là đủ. Cộng đồng đã phát hiện ra rằng bằng cách chuyển trình biên dịch cũng như một số thư viện cốt lõi của ngôn ngữ, mã nguồn (chứ không phải mã nhị phân) có thể được mang theo.

Tuy nhiên, C ++ được sử dụng rộng rãi trong các hệ thống quan trọng như trình biên dịch, nhân, hệ thống thời gian thực, hệ thống nhúng, ... Có một khía cạnh "mức độ thấp" của C ++ không thể bỏ qua khi nói về tính di động.


4
Tính di động không phải là một huyền thoại. Tính di động hoàn hảo là.
Malcolm

"Đây là nơi Java rất khác với C ++, trong đó mỗi ứng dụng là" đặc thù của máy "và không thể được chuyển mà không sửa đổi mã." Điều đó không đúng, nó phụ thuộc vào sự phụ thuộc. Nếu bạn chỉ sử dụng thư viện và thư viện tiêu chuẩn với các nguồn di động cho mục tiêu của mình, bạn mã hóa một lần và biên dịch trên mỗi mục tiêu. Nếu bạn mã hóa một cái gì đó có thể được chuyển mà không sửa đổi mã trong C ++ thì điều duy nhất bạn có thể cần sửa đổi là các tập lệnh xây dựng. Điều đó thậm chí không đúng trong mọi trường hợp.
Klaim

Chúng ta đừng quên rằng C ++ có thể được sử dụng như một ngôn ngữ cấp cao và cấp thấp. Rất nhiều mã C ++ được sử dụng trong các chương trình trong đó int 32 bit rất khác với int 64 bit. Tất nhiên, cấp cao sẽ luôn có thể mang theo được. Nhưng nó khác xa với việc khái quát hóa C ++
rahmu

Tôi nghĩ rằng bạn có thể đã hiểu sai những gì tôi đang nói: bạn có thể viết C ++ chính xác bằng int hoặc bất kỳ loại tiêu chuẩn nào mà không bận tâm đến những thứ cấp thấp. Chỉ cần xem các thư viện boost, hầu hết chỉ là mã cấp cao và điều đó đúng với rất nhiều dự án nguồn mở C ++. Bạn "có thể" ở mức thấp và nếu có, bạn cũng có thể tránh bất kỳ mã cụ thể nào cho đến khi bạn cần sử dụng API cụ thể của nền tảng. Nhưng nếu bạn không cần, thì bạn có thể viết C ++ hoạt động ở mọi nơi. Sự phụ thuộc vào nền tảng có thể tránh được và thường là trong mã thư viện.
Klaim

Chỉ cần chắc chắn rằng tôi rõ ràng: Tôi không nói rằng tất cả mã C ++ là di động, tôi đang nói rằng như vậy, tuyên bố của bạn là sai. Bạn có thể muốn sửa nó bằng một cái gì đó như: "Đây là nơi Java rất khác với C ++, trong đó mỗi ứng dụng là" dành riêng cho máy "và không thể được chuyển mà không sửa đổi mã hoặc, nếu mã thực sự là di động và bản dựng các kịch bản quản lý mục tiêu mới, không có ít nhất một phần biên dịch. "
Klaim

14

Đó không chỉ là ngôn ngữ - đó là các thư viện.

Cả Java và C ++ đều cung cấp các thư viện đa nền tảng. Java cung cấp một tập hợp phong phú hơn.


2
Java cung cấp một tập hợp phong phú hơn theo mặc định. Các thư viện tương tự có thể được tìm thấy cho C ++, chúng không phải là một phần của các thư viện chuẩn và bạn chỉ phải quyết định sử dụng thư viện nào (không phải là nhỏ, đặc biệt nếu chúng không được cài đặt).
Martin York

So sánh các thư viện chuẩn của Java với vũ trụ của các thư viện cho C ++ không thực sự là một so sánh hợp lệ. Java cung cấp một tập hợp phong phú hơn, cho dù bạn đang so sánh các thư viện tiêu chuẩn của từng thư viện hay bạn đang so sánh vũ trụ của các thư viện của mỗi thư viện.
Andy Thomas

3
Chắc chắn không đồng ý với điều đó. Mọi thứ trong thư viện Java đều có sẵn đã được C ++ sử dụng trong một số thư viện. Tôi thích thực tế là Java có tất cả ở một nơi nhưng để nói rằng nó phong phú hơn là không đúng. Có thể tính từ bạn đang tìm kiếm là 'tích hợp hơn'
Martin York

1
+1 sẽ upvote một lần nữa. Tôi nghĩ rằng các thư viện là yếu tố lớn nhất trong tính di động. Nếu bạn đang làm việc trong C / C ++ và làm bất cứ điều gì khác ngoài tính toán thuần túy, sẽ có các thư viện (đặc biệt là các phần của thư viện hệ thống) hoàn toàn khác nhau giữa Windows và Unix và khác biệt tinh tế giữa các hương vị khác nhau của Unix. Điều đó làm cho việc chuyển cổng trở nên khó khăn. Java về cơ bản không có vấn đề đó.
Tom Anderson

1
@Andy Thomas-Cramer: Tôi không so sánh bất cứ điều gì (dường như bạn đang có). Tôi đang nói rằng tuyên bố của bạn là không chính xác. Một trong những lợi thế mà Java có (và tất cả chúng ta đều yêu thích nó) là tất cả các thư viện tiêu chuẩn ở một nơi. Nói rằng họ giàu hơn chỉ là không chính xác.
Martin York

7

Sự khác biệt là Java sẽ chạy trên mọi nền tảng mà không cần biên dịch lại. Có một trình biên dịch C ++ cho mỗi nền tảng hoàn toàn không giống nhau.


6

Tất cả các câu trả lời bắt đầu bằng "Sự khác biệt là ...", hoặc bất cứ điều gì rất giống nhau, về cơ bản là sai (xin lỗi, nhưng đó là cuộc sống). Thực sự có hai sự khác biệt giữa hai.

Một (điều đó đã được đề cập rất nhiều) là một chương trình Java đã biên dịch có thể (hoặc ít nhất nên) chạy trên bất kỳ triển khai tuân thủ nào của Java, vì vậy ngay cả sau khi được biên dịch, bạn vẫn có thể di chuyển chương trình Java từ nền tảng này sang nền tảng khác mà không cần biên dịch lại . C ++ (ít nhất là bình thường) yêu cầu biên dịch lại cho mỗi nền tảng đích.

Mặt khác là Java (ít nhất là cố gắng) đảm bảo rằng tất cả Java được viết chính xác sẽ có thể mang theo được. Ít nhất là về lý thuyết, bạn không nên viết bất kỳ mã nào không di động.

C ++ cho phép bạn thực hiện một số thứ không thể mang theo được. Tiêu chuẩn C ++ chứa "cảnh báo" về rất nhiều thứ không khả dụng (ví dụ: cho bạn biết rằng bạn sẽ thực hiện hành vi được xác định hoặc hành vi không xác định), nhưng không nhất thiết phải cố gắng ngăn bạn thực hiện chúng . Ví dụ, nếu bạn muốn viết một hệ điều hành cho phần cứng sử dụng bus PCI, có lẽ bạn sẽ cần phải đọc / ghi bộ nhớ cấu hình PCI. Điều này rõ ràng sẽ không thể di chuyển đến các hệ thống không có bus PCI, nhưng nếu bạn đang viết một hệ điều hành cho phần cứng bằng bus PCI, điều đó khá cần thiết. C ++ cho phép nó mặc dù rõ ràng nó sẽ không thể mang theo được.


C ++ không biết gì về bus PCI cũng như phần cứng.
Nikko

tất nhiên là không, đó là những thứ cụ thể của nền tảng sẽ phải được đưa vào các thư viện cụ thể của nền tảng. Cũng như Java có thể có các thư viện nền tảng cụ thể nếu cần.
jwenting

1
@Nikko: Nó không biết gì về nó, nhưng nó cho phép bạn sử dụng những gì bạn biết về nó.
Jerry Coffin

@jwenting: Sự khác biệt là bạn có thể viết các thư viện dành riêng cho nền tảng trong C ++, nhưng bạn thường không thể viết chúng bằng Java.
Jerry Coffin

6

Bạn đã hiểu lầm các cơ sở. Các chương trình Java rất dễ mang theo, vì JVM cung cấp một hành vi tiêu chuẩn được đảm bảo giống nhau. Các chương trình C ++ có môi trường ít tiêu chuẩn hơn gần với phần cứng thực tế, vì vậy chương trình cần có khả năng xử lý các chi tiết cụ thể của nền tảng khác nhau - như kích thước của một int, căn chỉnh từ, v.v.

Bản thân JVM không dễ mang theo. Nhiệm vụ bất thường là chuyển một JVM hiệu năng cao sang một nền tảng hoặc kiến ​​trúc CPU khác.


+1 cho câu cuối cùng đó!
rahmu

2

Sự khác biệt là các chương trình Java (không phải là từ viết tắt) có thể được phân phối ở dạng có thể chạy trên bất kỳ máy tính nào có cài đặt JVM, nhưng C ++ thường được phân phối dưới dạng mã nguồn, rất thân thiện với người dùng hoặc là một bó của các nhị phân khác nhau cho các nền tảng khác nhau.


Huh? Có các trình biên dịch C ++ nhắm vào JVM và có các trình biên dịch Java nhắm vào mã gốc. Bạn có thể trích dẫn phần cụ thể của đặc tả ngôn ngữ C ++ nói rằng các chương trình C ++ phải được phân phối dưới dạng mã nguồn hoặc mã nhị phân cụ thể của nền tảng không?
Jörg W Mittag

Ở đó, tôi đã chỉnh sửa câu trả lời của mình để sử dụng ngôn ngữ ít dứt khoát hơn
Colin

2

Một trong những lý do Java được coi là di động là vì nó có các quy tắc cụ thể về cách định giá các biểu thức số học và cấm các triển khai đánh giá chúng theo bất kỳ cách nào khác, ngay cả khi đánh giá chúng theo cách bắt buộc sẽ yêu cầu mã chậm hơn so với đánh giá chúng chính xác hơn thời trang.

Ví dụ, được đưa ra

long thing1(int x) {
  return (x+1)-1L;
}
double thing2(int x, float y) {
  return x/y;
}

Các giá trị của thing1(2147483647)thing2(1123456700,11234567.0f)được yêu cầu lần lượt là -2147483649L và 99.9999923706054688, mặc dù các giá trị chính xác sẽ là 2147483647L và 100.0, và mặc dù trên một số mã nền tảng để tạo ra kết quả không chính xác về số sẽ chậm hơn mã để tạo ra kết quả không chính xác về số. kết quả (trên một số nền tảng 64 bit, buộc hành vi gói sau (x + 1) sẽ yêu cầu một lệnh bổ sung và trên nền tảng 8x87, buộc giá trị của 1123456700 được làm tròn thành một floatyêu cầu bổ sung so với tải đơn giản nó trực tiếp đến một thanh ghi chính xác mở rộng).


1
Lần đầu tiên một câu trả lời mới cho một câu hỏi cũ thực sự bổ sung một giá trị nào đó: Java có các yêu cầu số học rất chính xác và tất nhiên các kiểu dữ liệu nguyên thủy có kích thước và ngữ nghĩa cụ thể so với C ++. Không có câu trả lời khác kể từ ngày này đề cập đến điều này.

@Snowman: Bạn thích những ví dụ cụ thể được chọn như thế nào? Cá nhân nếu tôi đang thiết kế một ngôn ngữ, tôi sẽ không tạo ra ví dụ nào trả về giá trị của Java mà không sử dụng các biểu đồ thu hẹp để biểu hiện phụ (int)của ví dụ đầu tiên (x+1)trong ví dụ đầu tiên, cho tham số floatcủa ví dụ thứ hai x, nhưng rõ ràng tôi không thiết kế ngôn ngữ .
supercat

Tôi nghĩ rằng họ có ý nghĩa. Điều quan trọng đối với bất kỳ ngôn ngữ là có ngữ nghĩa được xác định rõ. Bất kể người ta có đồng ý với quyết định thiết kế ngôn ngữ nhất định hay không, điều quan trọng là có thể xem mã và biết cách hoạt động của nó. Java thường làm điều đó, với một vài trường hợp hành vi không xác định.

1

Khối lượng công việc cho các công cụ hỗ trợ thực sự tương tự nhau, sự khác biệt nằm ở chỗ khác. Khi một chương trình C ++ đã được biên dịch cho một nền tảng, bạn phải biên dịch lại nếu bạn muốn sử dụng nó trên một nền tảng khác. Tuy nhiên, khi một chương trình java đã được biên dịch, bạn có thể di chuyển nó sang bất kỳ nền tảng nào khác có môi trường thời gian chạy mà không phải biên dịch lại.


1

Trả lời tiêu đề "Tính di động có phải là một huyền thoại không?", Thay vì "Cái nào tốt hơn về tính di động, Java hay C ++", tôi sẽ nói rằng tính di động một phần là có thể, nhưng tính di động hoàn toàn thì đó là một huyền thoại.

Một cái gì đó mà tôi khăng khăng viết, và nó áp dụng cho câu hỏi này, đó là các nhà phát triển không còn làm việc chỉ với các ngôn ngữ lập trình, mà, với các khung lập trình đầy đủ.

Và những khung đó, bao gồm thư viện, cơ sở dữ liệu, giao diện đồ họa.

Ngôn ngữ lập trình nào, hoặc khung lập trình nào dễ mang theo hơn?

Vâng, nó phụ thuộc vào ứng dụng của bạn. đang cố gắng để đạt được.


1

Vấn đề là "bạn" không viết JRE mà bạn viết mã Java chạy trên bất kỳ JRE nào . "Bạn" làm viết mã C ++ mà có thể yêu cầu thay đổi bởi bạn trước khi nó sẽ biên dịch trên nền tảng khác.


0

Nhiều người quên hoặc không tính đến thực tế của Java khi họ nói rằng "đó là 100% di động" hoặc các cụm từ như thế.

Gần như tất cả các Tập đoàn / Nhà phần mềm lớn đều có ít nhất 1 triển khai Java tại nhà với một JRE liên quan trong quá khứ và một số vẫn duy trì nó, ví dụ như Microsoft, IBM và Apple đều có phiên bản Java của riêng họ phản ánh ý tưởng và suy nghĩ riêng về nơi mà ngành công nghiệp và ngôn ngữ như vậy nên đi.

Làm thế nào là "di động"? Một JRE bất cứ nơi nào bạn rẽ.

Và điều này là không cần xem xét những gì Sun / Oracle đã làm.

Một ví dụ về lý do tại sao mã Java không thực sự xa C và C ++ về khả năng di động là GUI và máy chủ đồ họa, Apple đã triển khai khung GUI không chuẩn cho JRE của riêng mình, do đó, có rất nhiều đau đầu và làm việc gấp đôi cho bất cứ ai muốn tạo / chuyển GUI bằng Java cho các máy của Apple và về cơ bản họ buộc phải đối phó với Quartz (làm thế nào về mặt "đòn bẩy" và ngôn ngữ cấp cao?).

Đôi khi, ngay cả những từ được sử dụng phổ biến nhất cũng không thực sự phản ánh ý nghĩa mà mọi người thường dành cho chúng, với tôi thuật ngữ "tính di động" trong thế giới Java giống như "triển vọng" theo nghĩa thông thường; về mặt thương mại và tài chính có triển vọng tốt hơn cho bạn nếu bạn áp dụng Java thay vì các ngôn ngữ khác (ít nhất là tại thời điểm Java ra đời) bởi vì bạn đã thực hiện rất nhiều công việc ở một bên (bạn nhận được JRE về bất cứ điều gì đó có thể được coi là một "máy tính") và cơ sở mã của bạn có khả năng di động vì nó là như vậy, bạn cần ít tài nguyên hơn để chuyển chương trình của mình, đó là, cho dù tài nguyên là tiền, thời gian hay nhân lực không thành vấn đề, nó thấp hơn ngưỡng so với các công nghệ khác và đó là những gì Java dành cho, nó đang hạ thấp ngưỡng đó.

Tất nhiên điều này là đúng nếu bạn chấp nhận các tiền đề của Java, có nghĩa là một máy ảo có bộ sưu tập rác, có nghĩa là nó tiêu tốn nhiều tài nguyên hơn nếu so với ngôn ngữ bản địa, nếu bạn thực sự muốn tận dụng tối đa CPU hoặc máy chủ của bạn đừng nghĩ rằng bạn có thể chấp nhận Java trừ khi bạn thực sự thiếu tài nguyên hoặc công ty của bạn rất nhỏ.

Tôi vẫn phải tìm một ứng dụng Java không tầm thường duy nhất chỉ chứa 1 phiên bản cho mỗi dòng mã hoặc chức năng (còn gọi là không có bất kỳ nội dung cụ thể nào về nền tảng) và nó có thể di động 100% trong số tất cả các JRE chính.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.